次のファイルがあります
header start
stuff
header end
pos LV file LVG size
1 a1 AAA BBB 100
2 b1 AAC BBB 1000
3 a3 AAB BBB 47
4 b6 AAC BBB 1000
a
2番目の列から始まる行数を数える必要があります。 Googleでこれを見つけました。
awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' file
ただし、出力が行数にすぎないようにコンテンツをフィルタリングする必要があります。以下を追加しました。
awk '/LVG/ || $2 ~ "^a"' file | awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' | tail -1
awk
これが私に必要な作業ですが、これらすべてが1つのコマンドで実行できるかどうか疑問に思います。
答え1
最も基本的な要件は次のとおりです。
awk '$2~/^a/{c++} END{print c+0}'
2番目の列をチェックし、正規表現の比較で始まることを確認し、a
カウンタを増やしますc
。ファイルの最後にカウンタが印刷されます。実際に増加しない数字も印刷されることを保証するために、すでにゼロ以外のc
場合はc+0
変更されないと印刷しますが、まだ初期化されていない場合は数字として解釈されるようにします。c
c
「ヘッダー」セクションを妨げる「残る」トークンがないことを確認するために、最初のチェックは最初の列が整数であることを確認することです。
awk '$1+0==$1 && $2~/^a/{c++} END{print c+0}'
ここでのアイデアは、数値の場合は$1+0
算術的に「何も追加しない」と解釈されますが、$1
awk
文字を追加0
「テキスト」の場合、$1+0
数値の場合にのみ変更されます。$1
より複雑なチェックのために行をすぐにスキップするだけでなく、「ヘッダーの終わり」行が表示されるまで行が考慮されないようにすることもできます。
awk 'f==2&&$2~/^a/{c++} f==1&&NF{f++} $0=="header end"{f=1} END{print c+0}'
行が見つかると、フラグはf
1に設定され、ヘッダーの後の空でない最初の行に設定され、2番目の列が検証される行にのみ設定されます。header end
2
f
2
答え2
私が提案するのはawk
解決策ではなく、grep
レコード構造に頼ることです。
$ grep "^[0-9]\+[[:blank:]]\+a[0-9]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[0-9]\+$" file | wc -l
2
答え3
awk 'NR==1 ,/^header end$/ { next };
!skip_hdr { skip_hdr=1; next }
($2 ~ /^a/) { count++ }
END{ print count+0 }' infile
NR==1 ,/^header end$/ { next }
:
ファイルの先頭から最初の行に移動しますheader end
。これは次の行をスキップします。ヘッダーの開始 もの 頭と尾
!skip_hdr { skip_hdr=1; next }
:
ヘッダー行をスキップpos LV file LVG size
。($2 ~ /^a/) { count++ }
:2番目の列が文字で始まる行数を
計算します(大文字と小文字を区別しません)。a
END{ print count+0 }
:
最終カウント値を印刷します。
答え4
簡単な解決策
説明と一致:2番目の列から始まる行数の計算これで十分です。
awk '$2 ~ /^a/ { count++ } END {print count}' file
grep(より速くする必要がある)コマンドを使用することもできます。
grep -c '^[0-9][0-9]* *a' test.txt
これはまた、最初のフィールドが数値(公開された例では必要なものであると仮定)であり、フィールド区切り文字が空白でなければならないという点でより具体的です。
もっと深く見る
ただし、公開した最初のソリューションは次のとおりです。
awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' file
全く違うことをしました。
このファイルに次のように入力します。
> cat file
header start
stuff
header end
pos1 LV file LVG size
1 a1 AAA BBB 100
2 b1 AAC BBB 1000
3 a3 AAB BBB 47
4 b6 AAC BBB 1000
5 c9 BBA CBA 20
pos2 LV file LVG size
1 a1 AAA BBB 100
2 b1 AAC BBB 1000
pos3 LV file LVG size
1 a1 AAA BBB 100
2 b1 AAC BBB 1000
3 a3 AAB BBB 47
公開したコードは、各(他の)ヘッダーの結果を印刷します。
> awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"=="a[i]-1}' test.txt
==2
pos1 LV file LVG size==5
pos3 LV file LVG size==3
pos2 LV file LVG size==2
つまり、空のタイトルに2行、タイトル「pos1」の後に5行など...
このような計算が必要かどうかわかりません。カウントから1を引く理由も不明です。
唯一の追加要件は、2番目のフィールドのみを計算することです。a
$ awk '/LVG/{p=$0} $2 ~ /^a/ {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1
最初のフィールドも数値でなければならない場合(上記のgrepコマンドに似ています):
$ awk '/LVG/{p=$0} ($1+0!=0)&&($2~/^a/) {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1