我的文件中有數百萬筆記錄,如下所示
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