[英]if value from one column is present in another columns then ignore/delete the line in output using awk
我想看看 column2 值是否存在於 column3 中,反之亦然,如果這是真的,那么我想從 output 中刪除它。
樣本.txt
3 abc def
5 ghk lmn
8 opq abc
10 lmn rst
15 uvw xyz
4 bcd abc
89 ntz uhg
到目前為止我有
awk ' {
x[$2]=$2
y[$3]=$3
if (!(($2 in y) ||( $3 in x)) )
{
print $1,$2,$3
}
} ' sample.txt
我想要 output 如下。
15 uvw xyz
89 ntz uhg
我知道 awk 逐行讀取文件並且我的代碼不兼容,因為它不檢查尚未看到的未來數組索引。 因此報告第一次發生。 想看看這是否可以在 awk 中以更簡單的方式完成,因為我的真實日期集非常龐大(多達 500 萬行,400-500 兆字節)。 謝謝!
使用兩遍輸入文件的一個awk
想法:
awk '
# 1st pass:
FNR==NR { seen[$2]++ # increment our seen counter for $2
if ($2 != $3) # do not increment seen[] if $2==$3
seen[$3]++ # increment our seen counter for $3
next
}
# 2nd pass:
seen[$2] <= 1 && # if seen[] counts are <= 1 for both
seen[$3] <= 1 # $2 and $3 then print current line
' sample.txt sample.txt
這會產生:
15 uvw xyz
89 ntz uhg
一遍又一遍地復制前 4 行,直到sample.txt
包含約 400 萬行,然后運行此awk
腳本,生成相同的 2 行 output,並在我的系統上花費約 3 秒(在低端 9xxx 上運行的 VM) i7).
另一個awk
想法使用一些額外的 memory 但只需要一次通過輸入文件:
awk '
{ seen[$2]++
if ($2 != $3)
seen[$3]++
if (seen[$2] <=1 && seen[$3] <= 1)
lines[++c]=$0
}
END { for (i=1;i<=c;i++) {
split(lines[i],arr)
if (seen[arr[1]] <= 1 && seen[arr[2]] <= 1)
print lines[i]
}
}
' sample.txt
這也會產生:
15 uvw xyz
89 ntz uhg
這一個的性能將取決於唯一的 $2/$3 值的數量,因此必須分配/處理的 memory 的數量。 對於我的 400 萬行sample.txt
(其中 400 萬行是重復行,因此很少使用額外的 memory),運行時間約為 1.7 秒......比 2 遍解決方案(~3 秒)好一點但是對於真實世界的數據(具有大量獨特的 $2/$3 值),我猜時間會更近一些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.