如何使用 sed、awk、grep 和 wc 格式化 bash 循環

如何使用 sed、awk、grep 和 wc 格式化 bash 循環

因此,我有一個文字文件,需要從中提取特定行併計算特定列中數字出現的次數。我有大約 100 個這樣的文件。我可以透過小步驟完成它,但想使用 bash/ksh 完成它:

foreach i *h3
sed '4p;55p;77q;d' $i >> output.txt
end 

^^^^這只會從每個 h3 檔案中提取我需要的行

awk '{print $6}' output.txt | grep 'P2' | wc -l

^^^這只會從output.txt中提取第6列併計算P2出現在第6列中的次數

有沒有辦法將所有這些合併到 bash/ksh 腳本中?

答案1

如果我理解正確的話:

  • 您想要計算幾個檔案(名為 *h3)的第 4,55 行和 77 行的第 6 個欄位中的任何位置有多少次「P2」?

您可以使用 1 awk 來完成此操作:

awk '
( FNR==4 || FNR==55 || FNR==77 ) {
    if ( $6 ~ "P2" ) { occurence++ } 
}
END {
    printf "There was: %d P2 ", occurence
    printf " among the 6th field on lines 4,55 or 77 of the *h3 files\n"
}' *h3

注意:如果您想要精確匹配,請更改$6 ~ "P2"$6 == "P2"(而不是 grep,就像您在自己的範例中使用的那樣,以便它也匹配:somethingP2otherthing及其變體)

FNR = 檔案的記錄數 = 目前檔案的行數(即每個檔案的第一行從 1 重新開始)(目前檔案的名稱也可以透過內部變數 FILENAME 得知)

(NR = 這裡不起作用,因為它是自開始(不是自當前文件開始以來)讀取的(總)數量或記錄)

答案2

當然。這是一種方法

p2_count=0
for f in *h3; do
    for ((n=1; n<=77; n++)); do
        IFS= read -r line
        if [[ $n == 4|55|77 ]]; then
            echo "$line"
            set -f
            set -- $line
            set +f
            if [[ $6 == *P2* ]]; then
                ((p2_count++))
            fi
        fi
    done < "$f"
done > output.txt
echo "saw P2 in 6th column $p2_count times"

答案3

或使用巴什單行:

for i in *h3; do sed '4p;55p;77q;d' $i | awk '{print $6}' | grep 'P2'; done | wc -l

或更短使用grep -c

for i in *h3; do sed '4p;55p;77q;d' $i | awk '{print $6}'; done | grep -c 'P2'

答案4

通常,當問題詢問“如何使用特定工具在 bash 循環中? ”,部分答案是“不要使用 bash 循環,使用(部分或全部)工具本身”。有時答案的一部分甚至是“不要使用那些工具,請使用這個”。

你想要的可以單獨完成awk,不需要 shell 循環。或sedgrepwc

awk 'BEGIN {OFS="\t"}
     FNR ~ /^(4|10|17)$/ && $6 ~ /P2/ {count++}
     ENDFILE { print FILENAME, count; count=0 }' *h3

筆記:文件結束 是 GNU 特有的awk。它不適用於其他版本的awk.

此版本還列印所有文件的累積總數:

awk 'BEGIN {OFS="\t"}
     FNR ~ /^(4|10|17)$/ && $6 ~ /P2/ {count++; total++}
     ENDFILE { print FILENAME, count; count=0 }
     END { print "---", total,"total" }' *h3

END{}區塊列印總數,並粗略地嘗試將實際總數與恰好具有檔案名稱「total」的任何檔案區分開。它透過---在第一個欄位中列印,然後列印總計,然後total在第三個欄位中列印字串來實現此目的。這遠非完美,但在許多情況下已經足夠好了。這比wc根本不嘗試好。

相關內容