クエリで変数を参照するとシェルでエラーが発生する

クエリで変数を参照するとシェルでエラーが発生する

Google Bigqueryテーブルにアクセスするためにシェルでクエリを実行しています。エラーの原因を特定できません。

#!/bin/bash

file_path='/home/vikrant_singh_rana/test_bq_file.csv'

{
    read
    while IFS=, read -r name local_unit region_unit
    do
        test_tablename=XYZ_KLM_${name}
        echo $test_tablename
        bq query --format=pretty --use_legacy_sql=false --project_id='test-data-project' "select DATE(COLLECTTIME) DATE,count(distinct COLLECTTIME) as record_count FROM `${project_id}.Test_INGEST.${test_tablename}` where DATE(collecttime) >= '2020-12-01' group by DATE order by DATE asc;"
    done
} < $file_path

以下は、読み取る入力ファイルです。

vikrant_singh_rana@cloudshell:~$ cat test_bq_file.csv
name,local_unit,region_unit
AAAAA,hour,cell
BBBBB,15min,cell

エラーは次のとおりです。

read_bq_table.sh: line 22: .Test_INGEST.XYZ_KLM_AAAAA: command not found
Error in query string: Error processing job 'test-data-project:bqjob_r54dd3bbd143fcd42_0000017667292a54_1': Syntax error: Unexpected keyword WHERE at [1:81]

答え1

二重引用符で囲まれた文字列

"select DATE(COLLECTTIME) DATE,count(distinct COLLECTTIME) as record_count FROM `${project_id}.Test_INGEST.${test_tablename}` where DATE(collecttime) >= '2020-12-01' group by DATE order by DATE asc;"

この部分

`${project_id}.Test_INGEST.${test_tablename}`

シェルではコマンドの代替として扱われます。これは、バックティックが引用符なしでまたは二重引用符で囲まれた文字列内に現れるときにコマンド置換を導入するためです。シェルは逆引用符内の変数を拡張し、その結果をコマンドとして実行しようとします。

$(${project_id}.Test_INGEST.${test_tablename})

`...`コマンドの実行によって生成された出力は、$(...)少なくとも意味のあるコマンドを使用して意図的に実行された場合、コマンドの置き換えを置き換えます。あなたの場合、バックティックはデータベース構文の一部であり、シェルはバックティックで操作を実行せずにリテラルバックティックに渡す必要があります。

バックティックを文字通り使用する場合は、引用を検討してください。

"select DATE(COLLECTTIME) DATE,count(distinct COLLECTTIME) as record_count FROM \`$project_id.Test_INGEST.$test_tablename\` where DATE(collecttime) >= '2020-12-01' group by DATE order by DATE asc;"

また、変数名の周りに不要な中かっこを削除しました。

理想的には、変数の値をデータベースに挿入する前に削除することをお勧めします。少なくとも逆引用符を含む文字列を検出して拒否する必要があります。

また、表示されるコードは変数値を設定しているように見えません(これがproject_idエラーメッセージの前の文字列部分が空である理由です)。.Test_INGEST

関連情報