このファイルを読み取るためにawkステートメントを作成しようとしています。
A 1,2,3 *
A 4,5,6 **
B 1
B 4,5 *
次のファイルをビルドします。
A 1,2,3 * 3 1 0.333
A 4,5,6 ** 3 2 0.666
B 1 1 0 0
B 4,5 * 2 1 0.5
この新しいファイルでは、最初の3つの列は元のファイルと同じです。 4番目の列には、列2のカンマ区切り要素の数を含める必要があります。 5番目の列には、列3の文字数を含める必要があります。最後の列には、列4から列5の比率が含まれます(つまり、列5を列4で割った値)。
次のコードを試しています。
awk '{print $1"\t"$2"\t"$3"\t"(NF","$2 -1)"\t"length($3)"\t"(length($3)/(NF","$2-1))}' file1 > file2
しかし、私は次のような結果を得ます。
A 1,2,3 * 3,0 1 0.333333
A 4,5,6 ** 3,3 2 0.666667
B 1 2,0 0 0
B 4,5 * 3,3 1 0.333333
4列で私が何が間違っているのか理解できません。
答え1
(NF","$2 -1)
これをフィールド内のコンマで区切られた要素の数を返す関数として考えたいと思いますが、$2
そうではありません。NF
常にフィールド数です。記録。
代わりに、awkのsplit
関数を使用してsplit($2,a,",")
フィールドを$2
配列に分割しa
、要素数を返すことができます。printステートメントで明示的な "\ t"を使用する代わりに、出力フィールド区切り文字をタブに設定してコードを整理することもできます。
awk '{l2=split($2,a,","); OFS="\t"; print $1, $2, $3, l2, length($3), length($3)/l2}' file1
答え2
Perlのアプローチは次のとおりです。
$ perl -lane '@k=($F[1]=~/,/g); $i=$#k+2; $l=length($F[2]);
print "@F $i $l ", $l/$i' file
A 1,2,3 * 3 1 0.333333333333333
A 4,5,6 ** 3 2 0.666666666666667
B 1 1 0
B 4,5 * 2 1 0.5
またはprintf
きれいな形式を使用してください。
$ perl -lane '@k=($F[1]=~/,/g); $i=$#k+2; $l=length($F[2]);
printf "%s %-5s %-3s %s %3s %10f\n",@F,$i,$l,$l/$i' file
A 1,2,3 * 3 1 0.333333
A 4,5,6 ** 3 2 0.666667
B 1 1 0 0.000000
B 4,5 * 2 1 0.500000
説明する
-lane
:-l
各入力行から末尾の改行を削除します。-a
各入力行をスペースの配列に自動的に分割します@F
。これは-n
「入力ファイルを1行ずつ読み込む」を意味し、-e
スクリプトをコマンドライン引数として渡すことができます。@k=($F[1]=~/,/g); $i=$#k+2;
:配列には、@k
2番目のフィールドにあるすべてのコンマが含まれています。次に、$i
最大インデックスを@F
($#F
)プラス2に設定します。 i)配列は0から計算されるため、2を追加する必要があります。したがって、単一要素配列の最大インデックスはゼロになります。値ではなくコンマを計算するので、1,2
値は2つですが、値コンマは1つだけなので、1を追加する必要があります。$l=length($F[2]);
:$l
3Dフィールドの文字数です。print "@F $i $l ", $l/$i
:要求された情報を印刷します。@F
は入力ファイルの行で、残りはユーザーが要求したものです。