給定一個排序的文件,像這樣:如何根據sed中前一行和當前行中的匹配刪除當前行?
AAA 1 2 3
AAA 2 3 4
AAA 3 4 2
BBB 1 1 1
BBB 1 2 1
和
AAA 1 2 3
BBB 1 1 1
什麼用的sed實現這一目標的最佳途徑所需的輸出?
基本上,如果col以前一行的字段開頭,我該如何刪除它?其餘的數據必須保存在輸出中。
我想必須有一些方法來使用保持緩衝區,分支或測試命令來做到這一點。
給定一個排序的文件,像這樣:如何根據sed中前一行和當前行中的匹配刪除當前行?
AAA 1 2 3
AAA 2 3 4
AAA 3 4 2
BBB 1 1 1
BBB 1 2 1
和
AAA 1 2 3
BBB 1 1 1
什麼用的sed實現這一目標的最佳途徑所需的輸出?
基本上,如果col以前一行的字段開頭,我該如何刪除它?其餘的數據必須保存在輸出中。
我想必須有一些方法來使用保持緩衝區,分支或測試命令來做到這一點。
另一種方式:
awk '!($1 in a){print;a[$1]}' file
這可能與AWK來實現:使用awk
$ gawk '{if (last != $1) print; last = $1}' in.txt
AAA 1 2 3
BBB 1 1 1
也許有與sed
一個更簡單的方法,但是:
sed ':a;N;/\([[:alnum:]]*[[:space:]]\).*\n\1/{s/\n.*//;ta};P;D'
這將產生輸出
AAA 1 2 3
BBB 1 1 1
其不同之處在於這個問題,但說明相匹配:
如果山坳用相同的字段作爲前行開始,我怎麼刪除呢?
這可能會爲你工作(GNU SED):
sed -r ':a;$!N;s/^((\S+\s).*)\n\2.*/\1/;ta;P;D' file
或者只是:
sort -uk1,1 file
一個使用GNU awk
方式:
awk '!array[$1]++' file.txt
結果:
AAA 1 2 3
BBB 1 1 1
使用的sed:
#!/bin/sed -nf
P
: loop
s/\s.*//
N
/\([^\n][^\n]*\)\n\1/ b loop
D
首先,我們必須通過-n
標誌的sed,因此將只打印什麼,我們告訴它。
我們首先打印帶有「P」命令的行,因爲第一行將始終打印,我們將強制sed在我們需要時執行此行。
現在我們將做一個循環。我們通過「:」命令定義了一個帶有起始標籤的循環(在這種情況下,我們將標籤命名爲「loop」),必要時我們用「b」命令(或「t」測試命令)。這個循環很簡單:
\(
與\)
結束)。在這種情況下,我們將所有不是換行符的字符(即[^\n]
)都匹配到行尾。我們通過匹配至少一個非換行符後跟任意序列來完成此操作。這可以防止在換行符之前匹配空字符串。捕獲後,我們通過使用特殊變量\1
,其中包含由第一捕獲匹配的輸入匹配換行符隨後捕獲的結果。如果成功,我們有一條重複第一個字段的行,所以我們用「b」分支命令跳回到循環的開始位置。這可以被縮短成一條線(注意,我們已經改名爲「循環」標籤到「A」):
sed -e 'P;:a;s/\s.*//;N;/\([^\n][^\n]*\)\n\1/ba;D'
有趣,但不太什麼要求中,如果第六行是'AAA 5 6 7',問題會期望它被打印出來,但是你的代碼不會因爲'AAA'曾經被看到過。 (但是,由於這是公認的,誰也不知道。也許我誤解了這個問題) –
但它確實工作,如果文件排序 – Dinedal
他們是否排序? – 2012-10-01 19:19:26