1

我有一个这样的txt文件:

# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# WR
ABABABABABABABABAB
BABABBABABABABABAA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA
# SL
AAABABABABABABBABA
AAABBABABABABABABA

我想删除所有用于 SL 和 WR 的数据(例如)。所以我将只有:

# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA

我知道如何删除一行开始或包含某些内容,但不知道如何处理一行中的 3 行。

这是我用来删除包含某些内容的行的方法:

awk ' $2 !~ /SL/ && $2 !~ /WR/ ' test.txt > test_new.txt

我想知道是否有办法将所有三行一起删除。

4

3 回答 3

3

使用打印标志的纯awk解决方案(受dogbane启发):

$ awk '/^#/{p=1}/^# (SL|WR)/,/^#/{p=0}p' file
# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA

解释:

/^#/ {p=1}如果该行以#设置打印标志p开始1

/^# (SL|WR)/,/^#/{p=0}如果该行在开始范围内# SL# WR直到下一行开始#,则将打印标志设置为0

p如果打印标志不为零,则运行默认块,{print}否则0不打印任何内容。

顺序在这里很重要,首先打印标志在每个新记录处打开,并且仅对记录和SL关闭WR


使用record seperators

您可以通过设置变量来重新定义 arecord的含义。默认情况下,每条记录由换行符分隔,但对于您的示例 with 可以用作记录分隔符,并且仅打印第一个字段不是或的记录:awkRS#WRSL

$ awk '$1 != "SL" && $1 != "WR"' RS=# ORS=# file
# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA
#

这种方法的一个小问题是最后一个记录分隔符。一个简单的解决方法是将管道传输到sed '$d'

$ awk '$1 != "SL" && $1 != "WR"' RS=# ORS=# file | sed '$d'
# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA

注意:变量ORS是我们需要设置的输出记录分隔符,以便#在输出中显示。

于 2013-03-15T10:56:34.460 回答
3

使用sed

要删除# WR

sed -e '/^# WR/,/^#/ {/^# WR/d;/^#/!d}' file

要同时删除# WR# SL块:

$ sed -e '/^# WR/,/^#/ {/^# WR/d;/^#/!d}' -e '/^# SL/,/^#/ {/^# SL/d;/^#/!d}' file

# RIR1
ABABABABABABABABAA
ABABABABABABABABBA
# BR2
ABABABABABABABBABA
ABBABABABABABABABA

或者,按照 sudo_O 的建议:

sed -r '/^# (WR|SL)/,/^#/ {/^# (WR|SL)/d;/^#/!d}' file
于 2013-03-15T11:22:47.417 回答
0

预处理文件:

awk '/#/{print x}1' file | awk '$2!="SL" && $2 !="WR"' RS=
于 2013-03-15T11:00:10.130 回答