sed를 사용하여 복잡한 문자열 (정규식으로 선호) 찾기 및 바꾸기

다음 내용의 파일이 있습니다.

<username><![CDATA[name]]></username> <password><![CDATA[password]]></password> <dbname><![CDATA[name]]></dbname> 

첫 번째 줄의”이름 “을”something “으로, 두 번째 줄의”password “를”somethingelse “로,”name “을”이름 “으로 변경하는 스크립트를 작성해야합니다. 세 번째 줄은 “somethingdifferent”입니다. 파일에서 발생하는 순서에 의존 할 수 없으므로 “name”의 첫 번째 항목을 “something”으로 바꾸고 “name”의 두 번째 항목을 “somethingdifferent”로 간단히 바꿀 수는 없습니다. 실제로 내가 올바른 것을 찾고 바꾸고 있는지 확인하기 위해 주변 문자열을 검색해야합니다.

지금까지이 명령을 사용하여 첫 번째 “이름”항목을 찾아 바 꾸었습니다.

sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml 

하지만 작동하지 않으므로 이러한 문자 중 일부는 이스케이프 등이 필요할 수 있습니다.

이상적으로는 d 정규식을 사용하여 두 개의 “사용자 이름”항목을 일치시키고 “이름”만 바꿀 수 있기를 바랍니다. 이와 비슷하지만 sed :

<username>.+?(name).+?</username> 

그리고 괄호 안의 내용을 “something”으로 바꿉니다.

가능합니까?

댓글

  • 극도로 인위적인 경우가 아니면 거의 모든 정규 표현식 기반 솔루션이 위험 할 수 있습니다. 입력 형식이 변경 될 때마다 중단됩니다. 정규 표현식은 XML, SGML 또는 파생물을 처리하는 데 적합하지 않습니다.
  • 승인되었습니다! 예를 들어 XQuery를 사용해보세요. w3schools.com/xquery/default.asp . XML 콘텐츠를 검색하고 조작하기위한 W3C 표준입니다.

답변

sed -i -E "s/(<username>.+)name(.+<\/username>)/\1something\2/" file.xml 

이것은 여러분이 찾고있는 것입니다.

설명 :

  • 첫 번째 부분의 괄호는 그룹 (실제로 문자열)을 정의합니다. 두 번째 부분에서 재사용 할 수 있습니다.
  • \1, \2 등 두 번째 부분에서는 첫 번째 부분에서 캡처 된 i 번째 그룹 (번호는 1로 시작)
  • -E는 확장 정규식을 활성화합니다 (+ 및 그룹화).

댓글

  • -E 옵션에 대한 +1
  • it 이름이 (original name) + "-E" 인 백업 파일이 남습니다.
  • OSX에서 ' sed : 1 : " s / (< 사용자 이름 >. +) name (. + … " : \ 1 아님 RE '에 정의되어 있습니다. 이 질문의 정확한 예를 파일에 붙여 넣었습니다. 그런 다음 해당 파일에 대한이 답변의 명령을 실행했습니다. OSX의 구문이 다를 수 있습니까?
  • sed의 gnu 버전은 " -E " 매개 변수를 지원하지만 지원하지 않습니다. 공무원. 맨 페이지에도 언급되지 않았습니다. ' 확장 정규식을 사용하려면 대신 " -r " 매개 변수를 사용해야합니다.
  • @ deweydb 이 답변 에 따르면 \(\)를 사용해야합니다. () 대신.

답변

sed -e "/username/s/CDATA\[name\]/CDATA\[something\]/" \ -e "/password/s/CDATA\[password\]/CDATA\[somethingelse\]/" \ -e "/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/" file.txt 

s 앞에있는 /username/는 sed를 알려줍니다. 문자열 “username”이 포함 된 줄에서만 작동합니다.

Comments

  • 우아하고 효율적이며 케이스에 완벽하게 맞습니다. +1

답변

sed가 어렵지 않은 경우 대신 전용 도구를 사용하는 것이 좋습니다.

파일이 유효한 XML (3 개의 XML 모양 태그뿐만 아니라)이면 XMLStarlet을 사용할 수 있습니다. :

xml ed -P -O -L \ -u "//username/text()" -v "something" \ -u "//password/text()" -v "somethingelse" \ -u "//dbname/text()" -v "somethingdifferent" file.xml 

위의 내용은 정규 표현식으로 해결하기 어려운 상황에서도 작동합니다.

  • 현재 값을 지정하지 않고 태그 값을 대체 할 수 있습니다.
  • 값이 이스케이프되고 CDATA에 포함되지 않은 경우에도 값을 대체 할 수 있습니다.
  • 다음 경우에도 값을 대체 할 수 있습니다. 태그에는 속성이 있습니다.
  • 같은 이름을 가진 태그가 여러 개있는 경우 태그 발생 만 쉽게 바꿀 수 있습니다.
  • 수정 된 XML을 들여 쓰기하여 서식을 지정할 수 있습니다.

위의 간단한 데모 :

bash-4.2$ cat file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[name]]></username> <password>password</password> <dbname foo="bar"><![CDATA[name]]></dbname> </apprentice> </sith> bash-4.2$ xml ed -O -u "//apprentice/username/text()" -v "something" -u "//password/text()" -v "somethingelse" -u "//dbname/text()" -v "somethingdifferent" file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[something]]></username> <password>somethingelse</password> <dbname foo="bar"><![CDATA[somethingdifferent]]></dbname> </apprentice> </sith> 

답변

$ sed -e "1s/name/something/2" \ -e "3s/name/somethingdifferent/2" \ -e "s/password/somethingelse/2" sample.xml 

단순히 주소를 사용할 수 있습니다. 줄 번호를 나타내는 “s”앞의 숫자에서 s.

또한 마지막에있는 숫자는 sed에게 첫 번째 항목을 대체하는 대신 두 번째 일치 항목을 대체하도록 지시합니다. 시합.

답변

정규 표현식 부분에서 \[.*^$/를 인용해야합니다. 교체 부품의 s 명령 및 \&/ 및 줄 바꿈. 정규식은 기본 정규식 이며 또한 s 명령에 대한 구분 기호를 인용해야합니다.

/를 인용하지 않도록 다른 구분 기호를 선택할 수 있습니다. 대신 해당 문자를 인용해야하지만 일반적으로 구분 기호를 변경하는 것은 대체 할 텍스트 나 대체 텍스트에서 발생하지 않는 것을 선택하는 것입니다.

sed -e "s~<username><!\[CDATA\[name\]\]></username>~<username><![CDATA[something]]></username>~" 

그룹을 사용하여 대체 텍스트의 일부 부분이 반복되는 것을 방지하고 이러한 부분의 변형을 수용 할 수 있습니다.

sed -e "s~\(<username><!\[[A-Z]*\[\)name\(\]\]></username>\)~\1something\2~" sed -e "s~\(<username>.*[^A-Za-z]\[\)name\([^A-Za-z].*</username>\)~\1something\2~" 

Answer

“name”단어를 “something”단어로 바꾸려면 다음을 사용하십시오.

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml 

지정된 단어의 모든 항목을 대체합니다.

지금까지 모든 항목이 표준 출력으로 출력되며 다음을 사용할 수 있습니다.

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml > anotherfile.xml 

변경 사항을 다른 파일에 저장합니다.

답변

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -r, --regexp-extended use extended regular expressions in the script. 

따라서 속성 파일의 값을 대체합니다.

sed -i -r "s/MAIL\=(.+)/MAIL\[email protected]/" etc/service.properties 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다