ループ変数を使用して各ループから単語を取得する

ループ変数を使用して各ループから単語を取得する

私は各ループで単語を取得しようとしています。iに挿入する方法がわかりませんprint $2

while [ $i -lt 4 ] 
do
    A=$(awk -F_ '{print $2}' <<< 'one_two_test_three')
    echo $A
done

明らかに、これは次のように出力されます。

two
two
two
two

私が望むもの:

one
two
test
three

私は試した:

A=$(awk -F_ '{print $($i)}' <<< 'one_two_test_three')

役に立たない。

答え1

正しい方法は、()オプションを使用してbash/shell変数をawk引数としてスクリプトに渡すことです。-vvariable

i=1;
while [ $i -lt 5 ]; do
    A=$(awk -v i="$i" -F_ '{ print $i }' <<< 'one_two_test_three')
    echo $A
    ((i++))
done

出力:

one
two
test
three

答え2

データの解析にシェルループは必要ありません。

$ awk -F '_' '{ for (i=1; i<=NF; ++i) print $i }' <<<'one_two_test_three'
one
two
test
three

スクリプトは入力_を区切りリストに解析し、各フィールドを印刷します。

短く:

$ awk -F '_' 'BEGIN { OFS="\n" } { $1=$1 } 1' <<< 'one_two_test_three'
one
two
test
three

これは、出力フィールドの区切り文字を改行文字に設定し、レコードを印刷する前にレコード全体を強制的に再構成(新しい区切り文字を挿入)するようにします。

短く:

$ tr '_' '\n' <<<'one_two_test_three'
one
two
test
three

データによるループ:

tr '_' '\n' <<<'one_two_test_three' |
while read -r word; do
    printf 'Got "%s"\n' "$word"
done

これにより、データを複数回解析するために使用されるユーティリティは呼び出されません。

答え3

値に改行文字がないと仮定すると、次のようになります。コードが機能するには最小限の変更が必要です。を#!/bin/bash使用しているので、shebangは(kshまたはzsh)でなければなりません<<<

i=1
while [ "$i" -le 4 ] 
do
    A=$(awk -v var="$i" -F_ '{print $var}' <<< 'one_two_test_three')
    echo "$A"
    i=$((i+1))
done

ただし、文字列はシェルから出てくるので、次のように単純化できます。

IFS=_ read v1 v2 v3 v4 <<<'one_two_test_three'
printf '%s\n' "$v1" "$v2" "$v3" "$v4"

そして、値の配列(可変数の値)を使用します。

#!/bin/bash
IFS=_ read -a v <<<'one_two_test_three'
printf '%s\n' "${v[@]}"

より単純なシェルを使用する必要がある場合:

#!/bin/sh
IFS=_ read v1 v2 v3 v4  <<-_expandvar_
one_two_test_three
_expandvar_
printf '%s\n' "$v1" "$v2" "$v3" "$v4"

もちろん、変数を設定する必要がない限り、スクリプトでIFS値を設定するのに問題はありません。

#/bin/sh
a='one_two_test_three'
IFS=_
set -f
printf '%s\n' $a

この変数は引用符なしで使用されるため、安全ではない可能性があります。

関連情報