-1
A
回答
1
要认识到的主要问题是sed
在单独的行上运行,而不是在整个文件上一次运行,这意味着如果没有特殊处理,它不能从正则表达式获得多行匹配。为了一次操作整个文件,首先必须将整个文件读入内存。有很多方法可以做到这一点;其中之一是
sed '1h; 1!H; $!d; x; s/regex/replacement/' filename
这种工作方式如下:
1h # When processing the first line, copy it to the hold buffer.
1!H # When processing a line that's not the first, append it to the hold buffer.
$!d # When processing a line that's not the last, stop working here.
x # If we get here, we just appended the last line to the hold buffer, so
# swap hold buffer and pattern space. Now the whole file is in the pattern
# space, where we can apply regexes to it.
我喜欢用这一个,因为它不涉及跳标签。有些seds(特别是BSD sed,与* BSD和MacOS X一起提供)在涉及到这些seds时会有点儿诡诈。
所以,剩下的就是制定一个多行的正则表达式。由于您没有指定分隔符模式,因此我假设您要删除包含START
的第一行和包含END
的最后一行之间的行。这可以通过
sed '1h; 1!H; $!d; x; s/\(START[^\n]*\).*\(\n[^\n]*END\)/\1\2/' filename
正则表达式不包含任何壮观;主要是你必须小心地在正确的地方使用[^\n]
以避免超出行尾的贪婪匹配。
请注意,只有当文件足够小才能完全读入内存时,它才会起作用。如果不是这种情况下,我的建议是要在文件中的两个通行证使用awk:
awk 'NR == FNR && /START/ && !start { start = NR } NR == FNR && /END/ { end = NR } NR != FNR && (FNR <= start || FNR >= end)' filename filename
这种工作方式如下:由于filename
传递给awk
两次,awk
将处理文件的两倍。 NR
是总体记录(默认行),FNR
从当前文件中读取的记录数。在文件第一遍中,NR
和FNR
是相等的,之后它们不是。所以:
# If this is the first pass over the file, the line matches the start pattern,
# and the start marker hasn't been set yet, set the start marker
NR == FNR && /START/ && !start { start = NR }
# If this is the first pass over the file and the line matches the end line,
# set the end marker to the current line (this means that the end marker will
# always identify the last occurrence of the end pattern that was seen so far)
NR == FNR && /END/ { end = NR }
# In the second pass, print those lines whose number is less than or equal to
# the start marker or greater than or equal to the end marker.
NR != FNR && (FNR <= start || FNR >= end)
0
没有示例输入,所以猜测一个示例文件和patterns/line3 /和/ line6 /。
line1 #keep - up to 1st pattern line3 - including
line2 #keep
line3 #keep
line4 #delete up to last occurence of line6
line5
line6a
line7
line6b
line8 #delete
line6C#keep - the last line6
line9 #keep
line10 #keep
没有任何暗VOO斗,但低效方法可能是:
(sed -n '1,/line3/p' file; tail -r file | sed -n '1,/line6/p' | tail -r) > file2
的file2
将包含:
line1
line2
line3
line6c
line9
line10
解释:
sed -n '1,/line3/p' file; # prints line 1 up to pattern (included)
tail -r file | sed -n '1,/line6/p' | tail -r
#reverse the file
#print the lines up to pattern2
#reverse the result
1
要跟进Wintermute's答案,如果你发现不匹配,你可以沿途删除块,所以你不必保持整个文件存储:
sed '/^START$/{:a;N;/.*\nEND$/d;ba}'
(对不起,会回复Wintermute的回答,但显然我仍然需要50个声望点作为这个特权)
相关问题
- 1. SED/AWK:删除图案线条图案
- 2. 使用sed删除图案线
- 3. SED或AWK - 图案之间删除字符串
- 4. 的sed - 插入线图案之前
- 5. 删除图案之间的空行
- 6. SED删除线
- 7. 删除壳中两个图案之间的线
- 8. 删除线(包括该图案的),使用AWK或sed的
- 9. sed命令删除与图案的线条“></" and "/>”
- 10. 在树状行之间的sed删除
- 11. 两个图案之间的awk/sed插入线
- 12. SED:删除两个模式之间的特定线
- 13. 删除海图中折线图中两个值之间的线
- 14. 如何删除图案之间的线条,但保持线条与第二个图案
- 15. sed的:动态删除除通过图案
- 16. 删除与图案匹配的线条
- 17. 如何用sed中的一行替换两个图案之间的线条?
- 18. SED:在模式匹配后删除线,同时跳过几行,然后删除图案线
- 19. SED删除图案线条却忽略注释行以相同的模式
- 20. 删除UITableView中的UITableViewCells之间的线
- 21. sed:替换含有图案的线
- 22. 删除tabWidget和frameLayout之间的线
- 23. 删除图像之间的空间
- 24. 的sed +不同炭之间删除空格与 “” 它们之间的分隔符
- 25. Sed删除大括号之间的bash脚本中的行
- 26. 替代多个线条图案在sed
- 27. 删除单词之间/斜线
- 28. 使用sed,删除两个字符之间的所有内容
- 29. SED删除两个模式匹配之间的行
- 30. 使用SED删除之间的一切,包括代码
你能举个例子吗? – Alp
显示该样品输入的样品输入和您想要的输出。 – Cyrus
如果您通过https://regex101.com/ – Nassim