我的文件中有数百万条记录,如下所示
echo "NEW Cell"
grep "2553,24" out.2A25.20090308.64436.7.HDF.txt.text = 22.58 5.39 82.09 237
echo "NEW Cell"
grep "2555,20" out.2A25.20090308.64436.7.HDF.txt.text = 24.72 5.58 82.05 237
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75 5.62 82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34 5.58 82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2 5.57 82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69 5.62 82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74 5.60 82.30 120
echo "NEW Cell"
grep "2560,24" out.2A25.20090308.64436.7.HDF.txt.text = 19.38 5.54 82.30 170
echo "NEW Cell"
现在我想删除带有“grep”的行,条件是它是包含“New Cell”的行之间的唯一行。也就是说,如果新单元格之间有一行 grep,则应删除这一行。
这个怎么做?
我的输出应该是这样的
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75 5.62 82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34 5.58 82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2 5.57 82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69 5.62 82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74 5.60 82.30 120
答案1
AWK
解决方案:
awk 'NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }
/NEW Cell/{ f=1; n=NR+2; r=$0; next }
f && n-NR==1 && /^grep /{ gr=$0; next }1' file
/NEW Cell/{ f=1; n=NR+2; r=$0; next }
- 遇到线时NEW Cell
f=1
= 设置活动标志f=1
n=NR+2
- 设置n
为要处理的以下行的最大数量(接下来的 2 行)r=$0
- 捕获线next
- 跳转到下一条记录
f && n-NR==1 && /^grep /
- 遇到以关键字n-NR==1
开头的第二行(由 保证)grep
gr=$0; next
- 捕获grep
行并跳转到下一条(第三条)记录
NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }
- 遇到第三条关键线时(由 保证NR==n
)if (/NEW Cell/) { f=0 }
- 如果已处理部分下的第 3 行包含NEW Cell
- 重置当前处理f=0
(跳过所有先前捕获的行)else print r ORS gr
- 否则打印所有先前捕获的行
输出:
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75 5.62 82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34 5.58 82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2 5.57 82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69 5.62 82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74 5.60 82.30 120
答案2
紧凑型解决方案sed
:
sed '/NEW Cell/!{H;d;};x;/\n.*\n/!d'
如果该行不包含NEW Cell
执行,H
则将该行附加到保留空间并d
停止对该行的处理。
因此,进一步的命令仅应用于NEW Cell
行:x
交换模式空间和保持空间,因此该行现在位于保持空间中,并且可以附加更多行,而模式空间包含附加到最后一行的所有内容NEW Cell
。您的要求是行与行之间有多于一行NEW Cell
,因此模式空间中必须至少有两个换行符。如果没有,则删除它,不输出:/\n.*\n/!d
。
答案3
凭借基本的awk
...
版本 1 只会删除grep
OP 描述之后的行:
awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
else { f=1; s=$0 } } ! /^echo/ { print; f=0 } \
! /^echo/ && ! /^grep/ { print }' inputfile
版本 2 将删除单独的grep
行以及前面的非 grep 行,该行遵循 OP 的示例输出:
awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
else { f=1; s=s "\n" $0 } } /^echo/ { s=$0; f=0 } \
! /^echo/ && ! /^grep/ { print }' inputfile
版本 2 的可读形式...
/^grep/ {
if (found) { # found==true : already encountered first grep line
if (length(save) > 0) {
print save
save=""
}
print
} else {
found=1
save=save "\n" $0 # append the first grep line to saved preceding line
}
}
/^echo/ {
save=$0 # save this line for possible later printing
found=0
}
# print anything else
! /^echo/ && ! /^grep/ { print }
这个长格式可以通过将内容放入文件(例如awkfile
)和 中来运行awk -f awkfile inputfile
。
答案4
gawk '
/\n.+\n/{
printf("%s%s", RS, $0);
}' RS='echo "NEW Cell"\n' input.txt
解释:
RS='echo "NEW Cell"\n'
-RS
是输入记录分隔符,默认为换行符。现在改为echo "NEW Cell"\n
,因此,该字符串的所有出现都将被删除,并且它们之间的所有字符都成为记录项。/\n.+\n/{
- 仅适用于与此模式匹配的记录 - 换行符、一个或多个字符、换行符。因此,它仅匹配多行记录,单行记录不匹配,因为它只有一个\n
.printf("%s%s", RS, $0);
- 打印记录,前面带有RS
(echo "NEW Cell"\n
)。
输出
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75 5.62 82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34 5.58 82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2 5.57 82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69 5.62 82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74 5.60 82.30 120