[英]Scrubbing files from the shell
我的shell技能有些生銹,但是我想做的是獲取2個文件,並根據匹配字段從另一個文件中“清理”一個文件。 這是重要的部分,其余各行可以有所不同,但是如果關鍵字段匹配,它將被刪除。 例如,我的文件用豎線分隔,第二個字段是關鍵字段。
File 1
------
acme|widg001|green|plant a|<timestamp>
acme|widg102|blue|plant b|<timestamp>
acme|widg002|yellow|plant a|<timestamp
File 2
------
acme|widg001|blue|plant a|<timestamp>
acme|widg701|blue|plant a|<timestamp>
當我從文件1中擦除文件2時,我想要包含的結果文件是
New File
------
acme|widg102|blue|plant b|<timestamp>
acme|widg002|yellow|plant a|<timestamp>
理想情況下,該解決方案使我可以指定兩個以上的文件,即從文件1中擦除文件2、3和4。
任何幫助將是巨大的!
由於您要求使用Bash,所以我決定只使用Bash。 完全沒有外部程序。
IFS='|'
declare -A scrub
while read f1 f2 rest; do
scrub[$f2]=0
done < file2.txt
while read f1 f2 rest; do
if [ ! ${scrub[$f2]} ]; then
echo "$f1|$f2|$rest"
fi
done < file1.txt
這會緩存要先清除的值,然后遍歷第一個文件中的候選值,打印未清除的值。 它不漂亮,但是是Bash。
這個awk可以將多個文件作為參數: (file1必須是最后一個)
awk -F'|' 'ARGIND<ARGC-1{a[$2];next} !($2 in a)' fileN fileN-1..... file1
關鍵是awk的ARGC and ARGIND
變量的用法。
用3個文件測試
kent$ head f*
==> f1 <==
acme|widg001|green|plant a|<timestamp>
acme|widg102|blue|plant b|<timestamp>
acme|widg002|yellow|plant a|<timestamp>
==> f2 <==
acme|widg001|blue|plant a|<timestamp>
acme|widg701|blue|plant a|<timestamp>
==> f3 <==
acme|widg102|blue|plant a|<timestamp>
acme|widg701|blue|plant a|<timestamp>
kent$ awk -F'|' 'ARGIND<ARGC-1{a[$2];next} !($2 in a)' f2 f3 f1
acme|widg002|yellow|plant a|<timestamp>
這看起來很近
join --check-order -v 1 -t\| -j 2 \
<(sort -t \| -k2 file1)
<(sort -t \| -k2 file2)
它打印
widg002|acme|yellow|plant a|<timestamp
widg102|acme|blue|plant b|<timestamp>
除了以下事實外,這似乎是正確的
join
期望輸入的方式,該輸出在鍵列上排序 --header
將使此內容更加清晰。 如果您堅持手動排序列,請嘗試以下FORMAT規范:
-o "$(echo 1.{1..5})"
哪個打印
acme|widg002|yellow|plant a|<timestamp
acme|widg102|blue|plant b|<timestamp>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.