끝 문자열이 시작 문자열과 다른 파일에서 줄을 추출하려고 합니다.
다음 형식의 입력 파일이 있습니다.
<item_id>6</item_id>
<info1>abc</info1>
<info2>123</info2>
<item_id>6</item_id>
<info1>def</info1>
<info2>456</info2>
<item_id>6</item_id>
<info1>ghi</info1>
<info2>789</info2>
<item_id>9</item_id>
<info1>jkl</info1>
<info2>012</info2>
<item_id>9</item_id>
<info1>mno</info1>
<info2>345</info2>
"6"에서 "9"까지 추출하고 싶습니다 (9는 임의의 숫자입니다)
시작은<item_id>6<\item_id>
끝은 <item_id>X<\item_id>
6이 아닌 X
예상되는 결과:
<item_id>6</item_id>
<info1>abc</info1>
<info2>123</info2>
<item_id>6</item_id>
<info1>def</info1>
<info2>456</info2>
<item_id>6</item_id>
<info1>ghi</info1>
<info2>789</info2>
나는 시도했다:
sed -n "/<item_id>6<\/item_id>/,/<item_id>!6<\/item_id>/p" input.file > output.6
sed -n "/<item_id>6<\/item_id>/,/<item_id>\!6<\/item_id>/p" input.file > output.6
sed -n "/<item_id>6<\/item_id>/,/<item_id>\{!6}<\/item_id>/p" input.file > output.6
sed -n "/<item_id>6<\/item_id>/,/<item_id>(6)\@!.<\/item_id>/p" input.file > output.6
sed -n "/<item_id>6<\/item_id>/,/<item_id>! 6<\/item_id>/p" input.file > output.6
답변1
이것이 올바른 형식의 XML 문서라고 가정하고 XMLStarlet을 사용하여 info_id
값이 인 노드를 선택한 다음 형제 노드 와 6
그 뒤에 오는 노드를 선택해 보겠습니다 .info1
info2
$ xmlstarlet sel -t -m '//item_id[. = 6]' \
-c . -nl \
-c './following-sibling::info1[1]' -nl \
-c './following-sibling::info2[1]' -nl file.xml
<item_id>6</item_id>
<info1>abc</info1>
<info2>123</info2>
<item_id>6</item_id>
<info1>def</info1>
<info2>456</info2>
<item_id>6</item_id>
<info1>ghi</info1>
<info2>789</info2>
또는 다음 노드의 이름을 무시하십시오.
xmlstarlet sel -t -m '//item_id[. = 6]' \
-c . -nl \
-c './following-sibling::*[1]' -nl \
-c './following-sibling::*[2]' -nl file.xml
답변2
아마도 이 GNU sed 스크립트가 여러분에게 적합할 것입니다:
sed '/<item_id>6<\/item_id>/{:1;n;/<item_id>[^6]<\/item_id>/{Q};b1};d' file
d
줄을 찾을 때까지 계속 삭제한 다음 스크립트가 종료되는 ([^6]) 줄을 찾을 때까지 6
내부 루프의 각 줄을 계속 인쇄합니다 .b1
not 6
Q
이는 다음에만 적용된다는 점을 이해하세요.캐릭터숫자( 6
또는 9
).
어떤 숫자와도 작동하려면 매우 혼란스럽습니다(GNU).
sed -e 'h;s,<item_id>\([0-9]*\)<\/item_id>,\1,;/^6$/!d;/^6$/{g;:1;h;s,<item_id>\([0-9]*\)<\/item_id>,\1,;t2;:3;g;n;b1};d;b;:2;/^6$/!Q;b3' file
몇 가지 변수를 사용하는 것이 더 좋지만 그다지 좋지는 않습니다.
reg='<item_id>\([0-9]*\)<\/item_id>'
item='6'
sed -e "h;s,$reg,\1,;/^$item$/!d;/^$item$/{g;:1;h;s,$reg,\1,;t2;:3;g;n;b1};d;b;:2;/^$item$/!Q;b3" file
그리고 POSIXfyed는 횡설수설처럼 보입니다.
sed -ne 'h;s,<item_id>\([0-9]*\)<\/item_id>,\1,;/^6$/!d;/^6$/{g;:1;h;s,<item_id>\([0-9]*\)<\/item_id>,\1,;t2;:3;g;p;n;b1;};d;b;:2;/^6$/!q;b3' file
다음 확장 코드만이 (?) 더 읽기 쉬울 수 있습니다.
reg='<item_id>\([0-9]*\)<\/item_id>'
item='6'
sed -ne 'h; # hold copy of line being processed.
s,'"$reg"',\1,; # extract included number.
/^'"$item"'$/!d; # Not the correct number?: get next line.
/^'"$item"'$/{
g; # restore line from hold buffer.
:1
h; # store successive lines in hold buffer.
s,'"$reg"',\1,; # extract the number (again).
t2
:3
g; # restore the line back from hold buffer.
p; # print the line.
n; # go to process next line.
b1
}; # end of loop.
d; # avoid printing this last line.
q; # quit the sed script.
:2
/^'"$item"'$/!q; # Test if the number is the one selected.
b3
' file
어쩌면 다른 언어나 도구를 사용해야 할 수도 있습니다.