特定の行を抽出し、特定の列の数字の出現回数をカウントする必要があるテキスト ファイルがあります。このようなファイルは 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" が何回あるかを数えたいですか?
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
単独で実行でき、シェルループは必要ありません。または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」であるファイルと実際の合計を区別しようと大雑把に試みます。これは、---
最初のフィールドに出力し、次に合計を出力し、3 番目のフィールドに文字列を出力します。これは完璧とは程遠いですが、多くの場合は十分です。 のように、まったく試みないtotal
よりはましです。wc