シェル スクリプトを使用して MySQL クエリで動的変数を渡す方法

シェル スクリプトを使用して MySQL クエリで動的変数を渡す方法

これは私のコードの一部です:

sample_1=''
sample_1_is_cancelled=''
sample_2=''
sample_2_is_cancelled=''
sample_3=''
sample_3_is_cancelled=''
sample_4=''
sample_4_is_cancelled=''
sample_5=''
sample_5_is_cancelled=''

while read -r insert
do
 eval sample_$i=$(echo $insert| awk -F'|' '{print $1}')
 eval sample_$i_is_cancelled=$(echo $insert| awk -F'|' '{print $2}')
         i=$(( i + 1 ))
         
         done < $logpath/source.txt

mysql -uroot -p -e" insert into ttable(sample_1, sample_1_is_cancelled, sample_2, sample_2_is_cancelled, sample_3, sample_3_is_cancelled, sample_4, sample_4_is_cancelled, sample_5, sample_5_is_cancelled)
                values($sample_1, $sample_1_is_cancelled, $sample_2 $sample_2_is_cancelled, $sample_3, $sample_3_is_cancelled, $sample_4, $sample_4_is_cancelled, $sample_5, $sample_5_is_cancelled);"

最大 5 セットの値が可能です。最小は 1 セットです。

以下のように変数をエコーすることができます。

eval echo \$sample_$i
eval echo \$sample_${i}_is_cancelled

しかし、同じ方法で挿入クエリの横に渡すことはできません。何か提案があれば教えてください。助けてください。

答え1

2 つの配列 (「フィールド」と「値」) を使用してこれを行う方法の例を次に示します。

#!/bin/bash

declare -a fields values

infile="./source.txt"
#infile="$logpath/source.txt"

i=0
while read -r insert; do
  # split "$insert" into a and b, using | as delimiter
  a="${insert%|*}"
  b="${insert#*|}"

  # create the field names from the loop counter $i
  let i++
  sfield="sample_$i"
  cfield="sample_${i}_is_cancelled"

  fields+=("$sfield" "$cfield")
  values+=("$a" "$b")
done < "$infile"


# show what's in the arrays:
declare -p fields
echo
declare -p values

# now build the SQL string, in parts:

# field names don't need to be quoted
f=$(printf "%s, " "${fields[@]}" | sed -e 's/, $//')

# this assumes values are strings and need to be quoted
v=$(printf "'%s', " "${values[@]}" | sed -e 's/, $//')

sql="$(printf "insert into ttable(%s) values (%s);" "$f" "$v")"

echo
echo "mysql -uroot -p -e \"$sql\""

次のsources.txtファイルがあるとします:

$ cat source.txt 
one|two
three|four
foo|bar
junk|more junk

スクリプトを実行すると、次の出力が生成されます。

declare -a fields=([0]="sample_1" [1]="sample_1_is_cancelled" [2]="sample_2" 
  [3]="sample_2_is_cancelled" [4]="sample_3" [5]="sample_3_is_cancelled"
  [6]="sample_4" [7]="sample_4_is_cancelled")

declare -a values=([0]="one" [1]="two" [2]="three" [3]="four"
  [4]="foo" [5]="bar" [6]="junk" [7]="more junk")

mysql -uroot -p -e "insert into ttable(sample_1, sample_1_is_cancelled, sample_2,
  sample_2_is_cancelled, sample_3, sample_3_is_cancelled,
  sample_4, sample_4_is_cancelled) values ('one', 'two', 'three', 'four',
  'foo', 'bar', 'junk', 'more junk');"

(読みやすさを向上させるために改行とインデントを追加)


注: シェル スクリプト自体のフィールド名または値を使用してさらに操作する必要がある場合 (つまり、SQL 挿入ステートメントで使用する以上の操作)、2 つの連想配列 (1 つはサンプル用、もう 1 つはキャンセルされたサンプル用) を使用し、それらの配列のキーとして $sfield 変数と $cfield 変数を使用する方がよいでしょう。私はこのようにスクリプトを書き始めましたが、タスクに対して複雑すぎる (また、SQL 文字列を作成するためにフィールドと値をマージするのにさらに作業が必要) ことに気付きました。そのため、インデックス付き配列 $fields と $values を使用するように簡略化しました。

関連情報