我正在尝试从文件中提取结束字符串与开始字符串不同的行
我有以下格式的输入文件:
<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>
X 不是 6
预期结果:
<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
找到一行,然后继续在内部循环中b1
打印每一行,直到not 6
找到 ([^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
也许您应该使用其他语言或工具。