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のみを抽出し、列6にP2が何回表示されるかを計算します。

これらすべてをbash / kshスクリプトに結合する方法はありますか?

答え1

私が正しく理解した場合:

  • 複数のファイル(* h3という名前)のうち4、55、77行の6番目のフィールドにある「P2」を何回計算しますか?

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

注:正確な一致が必要な場合は、(例で使用したようにgrepの代わりに:とその変形も一致するように)$6 ~ "P2"に変更してください。$6 == "P2"somethingP2otherthing

FNR = ファイル内レコード数 = 現在のファイルの行数 (つまり、各ファイルの最初の行は 1 から再開)

(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

または使用強く打つ1本のライン:

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シェルループなしで自分で行うことができます。またはsedまたはgrepまたはwc

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」のファイルと実際の合計を大まかに区別しようとします。最初のフィールドに印刷して---から合計を印刷し、total3番目のフィールドに文字列を印刷してこれを行います。これは完璧とは離れていますが、多くの場合に十分です。wcまったく努力しないよりも優れています。

関連情報