다음 내용의 파일이 있습니다.
<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