web-dev-qa-db-ja.com

bash + bashスクリプトによってファイルから変数と値を読み取る

次のファイル変数と値があります

# more file.txt
export worker01="sdg sdh sdi sdj sdk"
export worker02="sdg sdh sdi sdj sdm"
export worker03="sdg sdh sdi sdj sdf"

変数を読み取るためにソースを実行します

# source file.txt

例:

echo $worker01
sdg sdh sdi sdj sdk

今まではすべてが完璧です

ファイルから変数を読み取り、単純なbashループで値を出力したいので、2番目のフィールドを読み取って、変数の値を出力します。

#  for i in ` sed s'/=/ /g'  /tmp/file.txt | awk '{print $2}' `
   do  
   echo $i
   declare var="$i"
   echo $var
   done

しかし、それは変数ではなく値だけを出力します

worker01
worker01
worker02
worker02
worker03
worker03

予想される出力:

worker01
sdg sdh sdi sdj sdk
worker02
sdg sdh sdi sdj sdm
worker03
sdg sdh sdi sdj sdf
6
yael

export worker01="sdg sdh sdi sdj sdk"がある場合は、=をスペースに置き換えてexport worker01 "sdg sdh sdi sdj sdk"を取得します。スペースで区切られたフィールドは、exportworker01"sdgsdhなどです。

おそらく=で分割し、引用符を削除する方が良いので、シェルのみを使用します。

$ while IFS== read -r key val ; do
    val=${val%\"}; val=${val#\"}; key=${key#export };
    echo "$key = $val";
  done < vars
worker01 = sdg sdh sdi sdj sdk
worker02 = sdg sdh sdi sdj sdm
worker03 = sdg sdh sdi sdj sdf

keyには変数名、valには値が含まれます。もちろん、これは実際に入力を解析するのではなく、たまたまそこにある場合は二重引用符を削除するだけです。

5
ilkkachu

awkのみ:

awk -F'"' '{print $2}' file.txt
# To print the variable name as well:
awk '{gsub(/[:=]/," "); gsub(/[:"]/,""); if ($1 = "export") {$1=""; print $0}}' file.txt

それをループするには:

for i in "$(awk -F\" '{print $2}' file.txt)"; do
    var="$i"
    echo "$var"
done
my_array=($(awk -F\" '{print $2}' file.txt))
for element in "${my_var[@]}"; do
    another_var="$element"
    echo "$another_var"
done

ループで変数名も出力したい場合は、次のようにします。

#! /usr/bin/env bash -
while read -r line; do
    if [[ "$(awk '{print $1}' <<<"$line")" == 'export' ]]; then
        var_name="$(awk '{print $2}' <<<"$line" | awk -F'=' '{print $1}')"
        var_value="$(awk -F\" '{print $2}' <<<"$line")"
        echo -e "${var_name}\n${var_value}"
    else
        continue
    fi
done<file.txt

出力:

$ ./script.sh
worker01
sdg sdh sdi sdj sdk
worker02
sdg sdh sdi sdj sdm
worker03
sdg sdh sdi sdj sdf
3
jesse_b

まず、Perl互換の正規表現を使用して、このGNU grepコマンドで変数名を取得できます。

grep -oP 'export \K[^=]+' file.txt

次に、その出力をbash配列に読み込むことができます。

mapfile -t variables < <(grep -oP 'export \K[^=]+' file.txt)

組み込みのbash mapfile コマンドと process substitition を使用します。

最後に、変数名を反復処理し、 indirectパラメータ展開 を使用して値を取得します。

for v in "${variables[@]}"; do 
    printf "varname=%s\tvalue=%s\n" "$v" "${!v}"
done
varname=worker01        value=sdg sdh sdi sdj sdk
varname=worker02        value=sdg sdh sdi sdj sdm
varname=worker03        value=sdg sdh sdi sdj sdf
2
glenn jackman

このsedを使うことができます

sed -E 's/[^ ]* ([^=]*)="([^"]*)"/\1\n\2/' file.txt

またはこのawk

awk -F '"|=' '{split($1,a," ");print a[2]"\n"$3}' file.txt
0
ctac_