成功しませんでしたが、awk
ループ内でfor
コマンドを使用しようとしました。
データを取得するためにawk
で切り取りたい一連の文字列を含む変数があります。
私はそれを行う方法を知っていますが、私が本当に欲しいのは、データを連続してカットすることです。
だから私はこの変数を持っています:
var="data1,data2,data3"
そして私が今ここにいるところ:
for ((i=1; i<=3; i++))
do
echo $(awk -F, '{print $1}' <<< $var)
done
$1
ループによって$i
ですが、成功していません。
Awkスクリプトで二重引用符を使用してシェル変数を挿入することで、実行しようとしていることを実行できます。それでも、1つのリテラル$
を保持したい場合は、バックスラッシュでエスケープすることによって実行できます。
echo $(awk -F, "{print \$$i}" <<<$var)
これにより、各反復で$i
が1
、2
、3
に展開されます。したがって、awkは各フィールドを展開する$1
、$2
、$3
を参照します。
別の可能性は、-v
フラグを使用してシェル変数をawk変数として注入することです:
echo $(awk -F, -v i="$i" '{print $i}' <<<$var)
これにより、awk変数iが同じ名前のシェル変数の内容に割り当てられます。 awkの変数は、フィールドに使用される$
を使用しないため、iがawkの変数の場合、$i
でi-thフィールドを参照できます。
-v
を使用してawk変数を割り当てることは、特に任意の文字シーケンスを含めることができる場合、一般に安全なアプローチです。その場合、意図に反してコンテンツがawkコードとして実行されるリスクが少なくなります。しかし、あなたの場合、変数は単一の整数を保持しているので、それは問題ではありません。
さらに別のオプションは、awk自体でfor
ループを使用することです。その方法の詳細については、awkのドキュメントを参照(またはこのサイトを検索)してください。
awk は、j
(変数として)と$j
(フィールドインデックスとして)の両方を受け入れることができます。
for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done
"混乱" awk
の例では$i
どちらを使用するか(Shellまたはその独自の変数-優先)両方が$
プレフィックスで参照されるため。
sh 「ポータブル」スクリプティングの標準であるシェルはサポートしていません:
(( i=1; i<=3; i++; ))
および<<< $var
構成
また、可能であれば、seq
コマンドをfor
ループで使用して、番号シーケンス生成をより細かく制御することを検討してください。
この状況ではawk
の使用は過度に思われますが、tr
とwhileループはどうでしょうか。
tr , '\n' <<<"$var" | while read; do
echo $REPLY
done
出力:
data1
data2
data3
#!/bin/sh
var='data1,data2,data3'
unset data
while [ "$var" != "$data" ]; do
data=${var%%,*} # delete first comma and the bit after it
var=${var#*,} # delete bit up to first comma (and the comma)
printf 'data = "%s"\n' "$data"
done
ここでは、変数置換を使用して、var
変数の値からコンマ区切りの連続する各データフィールドを取得します。ループ内のdata
への最初の割り当ては、最初のコンマの後の$var
からすべてを削除します。次に、var
変数が変更され、最初のコンマまでの最初のビットが削除されます。
これは"$var" = "$data"
まで続きます。これは、文字列に対してこれ以上何もできないことを意味します。
この方法で、改行が埋め込まれたコンマ区切りのデータ文字列を処理できます。
var='line1
line2,data2,last bit
goes here'
上記の値がvar
にある場合、上記のスクリプトは
data = "line1
line2"
data = "data2"
data = "last bit
goes here"
埋め込まれた改行を気にしません。 めったにないawk
の呼び出しをループする必要があります。
awk
は、文字列をコンマ区切りのフィールドのセットとして完全に読み取り、これらをループできることに注意してください。
printf '%s\n' "$var" |
awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'
var='data1,data2,data3'
を使用すると、これは印刷されます
data1
data2
data3
IFS
変数を使用して$var
値をビットに分割し、set -f
を使用してファイル名の展開を無効にする別のシェルソリューション:
set -f
oldIFS=$IFS; IFS=','
set -- $var
IFS=$oldIFS; unset oldIFS
set +f
for data do
printf 'data = "%s"\n' "$data"
done