sed를 사용하여 파일을 수정할 때 어떤 문자를 이스케이프해야 합니까? [복사]

sed를 사용하여 파일을 수정할 때 어떤 문자를 이스케이프해야 합니까? [복사]

다음 sed 명령을 사용하고 있습니다(단어 경계 포함).

sed "7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/" < config.xml

다음 오류가 발생합니다.

sed: command garbled: 7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/

특수 문자를 이스케이프하려고 시도했지만 여전히 동일한 오류가 발생합니다.

sed "7 s/\<\<Filevalue=.*\/\/\>\>/\<Filevalue=\"true\"\/\>/" < config.xml

내가 뭘 잘못했나요?

편집하다:

이것은 더미 XML입니다. 파일값의 값은 달라질 수 있습니다.

XML 콘텐츠:

<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">

답변1

또한 구분 기호로 사용할 수 없는 슬래시는 백슬래시로 처리하거나 다른 구분 기호를 사용해야 합니다.

sed "7 s%\<<Filevalue=.*/>\>%<Filevalue="true"/>%"

또한 백슬래시를 사용하지 않고 큰따옴표 안에 큰따옴표를 포함하거나 작은따옴표로 전환할 수 없습니다.

또한 단어는 로 시작할 수 없으므로 <절대 \<<일치하지 않습니다.

답변2

당신이 잘못하고 있는 것은 정규식을 사용하여 XML을 구문 분석하려고 한다는 것입니다. 이것은 나쁜 생각입니다. 때로는 작동하지만 깨지기 쉬운 코드를 생성합니다. XML에는 줄 바꿈, 공백 및 중첩 태그를 허용하는 사양이 있습니다. 이러한 모든 항목은 정규식에서 매우 제대로 처리되지 않습니다.

실제 대답은 "파서를 사용하십시오"입니다.

나는 옵션으로 perl및를 권장하지만 다른 옵션도 있습니다.XML::Twig

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => {
        'File' => sub { $_->set_att( 'value', 'true' ) }
    }
);

$twig->parsefile('config.xml');    
$twig->print;

나는 XML의 내용에 대해 특정 가정을 하고 있습니다. 더 광범위한 예제를 제공할 준비가 되어 있다면 들여쓰기가 작동하는 방식으로 작동하는지 다시 확인하겠습니다.

편집하다:

귀하가 게시한 코드 조각에 따르면 이는 유효한 XML이 아니므로 위의 내용을 무시하십시오. 그럼에도 불구하고 소위 XML과 유사해 보이는 것을 사용하지 않는 것이 좋습니다. output.xml이는 온갖 고통과 불행을 초래하는 경로이기 때문입니다.

위의 코드는 다음에서 작동합니다.

<xml>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/> 
</xml>

여기에서 XML 유효성을 확인할 수 있습니다.http://www.xmlvalidation.com/index.php?id=1&L=0

XML이 아니라는 사실을 제쳐두면 다음과 같이 작동합니다.

#!/usr/bin/perl
use strict;
use warnings;

while ( <DATA> ) {
    #amend just line 7
   if ( $. == 7 ) { s,<Filevalue=".*">,<Filevalue="true">,; }
   print;
}
__DATA__
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">

다음 방법 중 하나로 이 작업을 수행할 수 있습니다.

perl -nle 'if ( $.==7) {s,<Filevalue=".*">,<Filevalue="true">,g;} print;' notxml.txt

답변3

choroba는 기본적으로 옳습니다. 그러나 그는 큰따옴표에 대해 오해의 소지가 있습니다. sed에는 문제가 아니지만 쉘에는 문제가 있습니다.

이스케이프 및 구분 기호만 필요합니다 * [ ] \ .(기본적으로 /). 귀하의 경우에는 이것이 가장 효과적이라고 생각합니다.

sed '7s%<<\([^>]*\)>>%<\1>%' file

유효한 경우 이 -i옵션을 사용하여 파일에서 바꾸십시오.

설명하다:

  • 표현식 세트는 \( \)오른쪽에서 다음으로 대체됩니다.\
  • [^>]*다음 오른쪽 꺾쇠괄호까지 모든 문자를 삼킵니다 .
  • 따라서 잘못된 이중 괄호 안의 내용은 이중 괄호 안의 동일한 표현식으로 대체됩니다. 이것은 단지 일어날 것입니다.한 번명령 g에 플래그를 추가 하지 않는 한 7행에 있습니다 .s

관련 정보