在 bash 中,我想将我的 TSV 表从 stdin 传递给 sqlite3,同时还传递要从变量导入的表的名称。如何才能做到这一点?例如:
#!/bin/bash
output_sql_db="$1"
input_tsv="$2"
table_name="$3
tail -n +2 "$input_tsv" | sqlite3 "$output_sql_db" '.import "/dev/stdin" ${table_name}'
当然,在此示例中,由于在 sqlite3 命令中使用了
${table_name}
,因此 '
未正确扩展。这应该怎么做呢?看来我找到的所有答案都只能显示手动处理其中一个(数据导入或传递表名称)。
使用 bash 定界文档,并决定何时/何处转义输入。在变量定义或命令创建时。
编辑:
我的观点是将您正在使用的语法/方法简化为类似的东西。
output_sql_db="$1"
input_tsv="$2"
table_name="$3
importfile=$(tail -n +2 $input_tsv)
sqlite3 "$output_sql_db .import ${importfile} ${table_name}"
示例中的主要问题是在命令周围使用单引号,这会阻止变量插值。如果要使用变量,需要使用双引号。
另一个(不相关的)可能的问题是您对
tail -n +2
的使用。如果您想要的是 $input_tsv 文件的最后 2 行,则正确的语法是 tail -2 $input_tsv
。
最后,您的
$input_tsv
变量的名称表明您的输入是制表符分隔的。如果是这种情况,您需要告诉 sqlite 您不使用它的默认分隔符 |
而是使用 Tab 字符,在 Bash 中可以写为 $'\t'
。
所以这个重写版本的脚本应该可以工作:
#!/bin/bash
output_sql_db="$1"
input_tsv="$2"
table_name="$3
tail -2 "$input_tsv" | sqlite3 -separator $'\t' "$output_sql_db" ".import /dev/stdin $table_name"
使用 Bash 过程替换和 SQLite 3.44.0 将 CSV 文件导入到 SQLite 数据库表中:
#!/bin/bash
# Uncomment to enable statement tracing.
#set -o xtrace
output_sql_db="$1"
input_tsv="$2"
table_name="$3"
# Check whether the table exists in the database.
table_exists="$(sqlite3 $output_sql_db << SQL
SELECT name
FROM sqlite_master
WHERE type = 'table'
AND name = '$table_name';
SQL
)"
if [ "$table_exists" == "$table_name" ]
then
skip_count="1"
else
skip_count="0"
fi
cat "$input_tsv" |
sqlite3 "$output_sql_db" ".import --csv --skip $skip_count "<(cat)" $table_name"
请注意,我将
/dev/stdin
替换为进程替换 <(cat)
。
如果
--csv
是制表符分隔文件,请将 --ascii
更改为 $input_tsv
。