ドキュメントを繰り返しながら、列内の最大文字長を見つけて返すスクリプトを作成しようとしています。私の目標は10,11,14,51ですが、スクリプトは78,78,78,78を返します。
for ((i=1;i<=4;i++)); do
awk -F"|" '{ print length($i) }' contact_d.csv | sort -nr | sed '1!d';
done
contact_d.csv
以下が含まれます:(ダミーデータを参照)とその例
Barrera|Wilkinson|(09) 1466 1886|[email protected]
Hopkins|Sellers|(07) 3814 2364|[email protected]
Hunter|Calderon|(01) 3984 0139|[email protected]
forループが私の目標を返さない理由を知っている人はいますか?
答え1
次のコードが機能します。
awk -F'|' '{for (i=1;i<=NF;i++) {len=length($i); if (len>lval[i]) {lval[i]=len; lpos[i]=FNR;}}} END{for (i in lval) printf("Longest value of column %d: %d (line %d)\n",i,lval[i],lpos[i])}' contact_d.csv
上記の例では、次を返します。
Longest value of column 1: 7 (line 1)
Longest value of column 2: 9 (line 1)
Longest value of column 3: 14 (line 1)
Longest value of column 4: 26 (line 2)
各行に対して、スクリプトはすべてのフィールド(1から
NF
フィールド数まで)を繰り返し、フィールドの長さ(変数に一時的に保存されている)l
がこれまでに見つかった最長の長さ(フィールドに保存されている)よりも大きいことを確認しますlval
。 =column) 数値インデックスの下の配列変数にあります。最初の行では
lval
まだ初期化されていません。それはまるで行動するでしょうすべてlval[i]
0です(実際にはそれよりも複雑です)。i
現在の行フィールドの長さがに格納されている値より長い場合、lval[i]
スクリプトはフィールドの現在の長さlval[i]
と現在の行番号(「auto」変数を介してアクセス可能FNR
)を配列変数に保存しますlpos
。ファイルの終わり(
END
条件)は、すべての列の最も長い長さとその場所を印刷します。ループを使用してfor (i in lval)
すべての構成を確認します。索引配列に存在するため、追加変数lval
に列数を格納する必要はありません(この場合は必要ですfor (i=1;i<=ncols;i++)
)。ブロックでは、END
「フィールド数」の概念がやや不明瞭になります。ただし、実際にはawk
アクセス時にファイルの最後の行に対応する値が通常使用されます。)。
シェルループから呼び出す必要はほとんどありませんawk
。ループで実行する必要があるほとんどの操作を実行できます。
最初の試行が失敗した理由は、コードが一重引用符で囲まれたスクリプト$i
にシェル変数()を提供しようとしましたが(提案されているように)、一重引用符はシェル変数の解釈をオフにします。awk
そうではありませんでした。対応していなかったでしょう)。