给定包含以下内容的文本文件:
1
2
REGEX1
3 - multiple line block
4
REGEX2
5
6
REGEX1
7 - multiple line block
REGEX2
8
9
REGEX1
10 - multiple line block
我想提取以下内容:
REGEX1
3 - multiple line block
4
REGEX1
7 - multiple line block
REGEX1
10 - multiple line block
即我想提取REGEX1和REGEX2之间的行,包括REGEX1,但不包括REGEX2。
我写了一个sed
脚本:
sed -n '/REGEX1/,/REGEX2/{/REGEX2/!p}' file
。
它工作正常,但是当给出这样的实例时:
1
2
REGEX2 REGEX1
3 - multiple line block
4
REGEX2
5
6
REGEX2 REGEX1
7 - multiple line block
REGEX2
8
9
REGEX2 REGEX1
10 - multiple line block
我的脚本只给了我:
3 - multiple line block
4
7 - multiple line block
10 - multiple line block
我希望它输出为:
REGEX2 REGEX1
3 - multiple line block
4
REGEX2 REGEX1
7 - multiple line block
REGEX2 REGEX1
10 - multiple line block
如何在没有低效率的情况下实现这一点(比如存储行号并再次浏览文件)?
答案 0 :(得分:2)
罢工1:sed用于单个行上的简单替换,即全部。除了s,g和p(以及-n)之外的任何其他东西都需要构造,而这些构造在20世纪70年代中期发明awk时都已经过时了。
Strike 2:你永远不应该使用范围表达式,因为它们使得琐碎的任务变得非常简单,但是当任务变得更加有趣时需要完全重写或重复条件,而是使用标志变量。
罢工3:sed不支持变量,因此您无法使用标记来判断您何时进入/离开您关注的文本块。
所以 - 只需使用awk:
import tablib
f = open('my_file.xlsx', 'rb')
data = tablib.import_set(f.read(), format='xlsx')
data[0]
以及第二组输入:
$ awk '/REGEX2/{f=0} /REGEX1/{f=1} f' file
REGEX1
3 - multiple line block
4
REGEX1
7 - multiple line block
REGEX1
10 - multiple line block
在任何UNIX机器上使用任何awk的任何大小的文件上面都可以健壮有效地工作。
有关选择文字块的更多方法,请参阅https://stackoverflow.com/a/17914105/1745001。
答案 1 :(得分:0)
这可能适合你(GNU sed):
sed -r '/^REGEX/h;G;s/^.*((REGEX1\b).*\n.*\2)/\1/;/\n.*REGEX1\b/P;d' file
将REGEX
存储在保留空间中,并将其附加到以下记录中。如果正则表达式在行的附加部分匹配,那么前半部分将删除该行。
编辑:
更改原始问题;以下更简单的解决方案满足:
sed '/^REGEX1/{:a;n;/REGEX2/!ba};d' file
但是如果REGEX2 REGEX1
重复,则需要将其更改为:
sed ':a;/^REGEX1/{:b;n;/REGEX2/!bb;ba};d' file
答案 2 :(得分:0)
sed -n '/REGEX1/,/REGEX2/{/REGEX1/{p;n};/REGEX2/!p}' file
添加/REGEX1/{p;n}
可确保打印REGEX1行,然后n
立即用下一行替换模式空间的内容。
n
。
但是,如果你有后续的sed命令, n
会烧掉你。你可以管道到另一个sed调用......或者使用awk。