我在一个文件中有类似的内容。我有一个行号列表,其中有 1,2,4。
- 可以满足所有需要的行号
- 提取之间的内容第一的和 的出现最后的的发生
</book>
数据:
</p><p>abc</p></book><book><p style="text-indent:0em;">def</p></book><book><p>ghi</p><p style="text-indent:0em;"></book><book><div><p>
</div><p>123</p></book><book><p style="text-indent:0em;">456</p><p>789</p><p style="text-indent:0em;"></book><book><div><p>
<div><p>nothing !!!</p></div>
</p><p>ABC</p></book><book><p style="text-indent:0em;">DEF</p></book><book><p>GHI</p><p style="text-indent:0em;"></book><book><div><p>JKL</p></div></book><div>
输入行号:1, 2, 4(我想在命令中输入)
期望的输出:
<book><p style="text-indent:0em;">def</p></book><book><p>ghi</p><p style="text-indent:0em;"></book>
<book><p style="text-indent:0em;">456</p><p>789</p><p style="text-indent:0em;"></book>
<book><p style="text-indent:0em;">DEF</p></book><book><p>GHI</p><p style="text-indent:0em;"></book><book><div><p>JKL</p></div></book>
答案1
1)提取特定行
在四行示例中,通过删除第三行可以轻松提取第一行、第二行和第四行:
sed 3d file
但你的文件可能更复杂,所以更通用的解决方案是
sed -e 1b -e 2b -e 4b -e d file
因此,对于应保留的每一行,您可以跳到脚本末尾b
并删除所有剩余文件。
对于更长的行号列表,您可能需要生成脚本:
sed $(for i in 1 2 4; do echo "-e ${i}b"; done) -e d file
但似乎不是行号的问题,而是<book>
该行是否有 s 的问题。如果这是真的,你最好忘记行号并执行
sed '/<book>/!d'
2)提取内容
正则表达式的贪婪*
不适合此类任务。这就是为什么我的个人版本sed
有一个命令选项,o
可以仅用匹配的部分s
替换:o
sed '/<book>/!d;s_<book>.*</book>_&_o'
但这对你不起作用,所以你需要更多的正则表达式杂耍:
sed '/<book>/!d;s_<book>_\n&_;s_.*\n__;s_\(.*</book>\).*_\1_' file
如果您的版本sed
不支持\n
替换字符串,请使用实际的换行符(通过反斜杠转义):
sed '/<book>/!d;s_<book>_\
&_;s_.*\n__;s_\(.*</book>\).*_\1_' file
答案2
和perl
:
#!/usr/bin/env perl
use strict;
use warnings;
use v5.10;
my @lines = (1, 2, 4);
while(<>) {
next unless $. ~~ @lines;
chomp;
s#.*?(<book>.*</book>).*#$1#;
say
}