
두 개의 sed 명령을 하나로 결합하고 싶지만 어떻게 해야 할지 잘 모르겠습니다. 여러 가지 방법을 시도했지만 성공하지 못했습니다.
결과적으로 특정 토큰 사이의 모든 슬래시를 백슬래시로 바꾸려고 합니다. 그 결과는 다음과 같습니다.
원천:
<FilePath>a/b/c/d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1/2/3/4</FilePath>
결과:
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1\2\3\4</FilePath>
레이블 사이의 텍스트를 변경하는 다음 명령을 찾았습니다.
sed -i -e 's/\(<FilePath>\).*\(<\/FilePath>\)/<FilePath>TEXT_TO_REPLACE_BY<\/FilePath>/g' test.txt
하지만 이 명령은 모든 텍스트를 대체합니다... 그래서 제가 원하는 것은 텍스트를 유지하고 다음 명령을 사용하여 슬래시를 백슬래시로 바꾸는 것입니다.
sed -e 's/\\/\//g' test.txt
하지만 이 둘을 결합하는 데 어려움을 겪습니다.
당신의 도움을 주셔서 감사합니다.
답변1
match()에 대한 세 번째 인수를 일치시키려면 GNU awk를 사용하십시오.
awk 'match($0,/(.*<FilePath>)(.*)(<\/FilePath>.*)/,a){ gsub("/","\\",a[2]); $0=a[1] a[2] a[3] } 1' file
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob/Smith</OtherTags>
<FilePath>1\2\3\4</FilePath>
위의 내용은 다음 입력으로 실행되었습니다.
$ cat file
<FilePath>a/b/c/d</FilePath>
<OtherTags>Bob/Smith</OtherTags>
<FilePath>1/2/3/4</FilePath>
답변2
주문하다
sed -e 's/\//\\/g' -e 's/<\\/<\//g' filename
산출
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1\2\3\4</FilePath>
답변3
확장된 정규식 패턴과 함께 GNU sed를 사용하면 태그가 인용문이나 주석의 일부가 아니라는 가정 하에 동일한 줄에서 열고 닫는 xml 태그인 FilePath를 단계별로 일치시킬 수 있습니다.
sed -Ee ' :a;s|<(FilePath)>([^/]*(/[^/]*)*)/([^/]*</\1>)|<\1>\2\\\4|;ta' file
perl -lpe '
s{<FilePath>\K.*?(?=</FilePath>)}
<$& =~ tr|/|\\|r>xge;
' file
태그의 시작과 끝 사이의 섹션을 분리하고 해당 섹션의 슬래시를 백슬래시로 변환합니다.
우리의 의도를 표현하기 위해 여러 줄의 정규식을 작성할 수 있습니다.
snr='
s|
<(FilePath)>
( [^/]* ([/][^/]*)* )
/
( [^/]* )
</\1>
|<\1> \2 \\ \4 </\1>|
'
ws=$'\t \n'
sed -E ":a;${snr//[$ws]/};ta" file
답변4
이는 sed 및 tr을 사용하여 파이프를 통해 구축된 매우 간단한 솔루션입니다. 다음을 가정합니다.
- 내부에는 중첩된 태그가 없습니다 (대체는 다음 이후
<FilePath>…</FilePath>
에만 수행됩니다 ).<
<FilePath>
<FilePath>
리터럴 문자열(no<![CDATA[<FilePath>/blah]]>
또는<mytag label="<FilePath>">
) 내에 나타나지 않습니다.- 마지막 줄에 종료 줄 바꿈이 없더라도 sed 구현은 이를 올바르게 처리합니다.
아이디어는 tr
줄 바꿈 <
과 개행을 사용하는 것입니다. 이 방법으로 sed가 "줄"을 처리할 때 실제로는 열기/닫기 태그와 텍스트 열기/닫기 태그 사이의 텍스트를 처리합니다.
tr '<\n' '\n<' | sed '/^FilePath>/ y:/:\\:' | tr '<\n' '\n<'
이것은 Perl 솔루션입니다. 다음을 가정합니다.
- 내부에는 중첩된 태그가 없습니다
<FilePath>…</FilePath>
. <FilePath>
리터럴 문자열(no<![CDATA[<FilePath>/blah]]>
또는<mytag label="<FilePath>">
) 내에 나타나지 않습니다.<FilePath>
항상</FilePath>
같은 줄을 따라가세요).
구성은 매우 자연스럽습니다. 즉, backslashify
내부 텍스트 에 기능을 적용합니다 <FilePath>…</FilePath>
. 정규식 .*?
은 비탐욕적 일치입니다. 같은 줄에 여러 블록이 있는 경우 욕심쟁이 일치는 .*
해당 줄의 모든 것을 처음부터 <FilePath>
마지막까지 대체합니다. 슬래시 바로 앞이나 뒤를 바꾸지 않고 중첩된 태그를 허용하는 고급 버전입니다.</FilePath>
<FilePath>…</FilePath>
s:(?!<<)/(?!>):\\:
tr:/:\\:
>
<
perl -pe 'sub backslashify {local $_ = $_[0]; s:(?!<<)/(?!>):\\:; return $_} s:(<FilePath>)(.*?)(</FilePath>):$1.backslashify($2).$3:e'