【问题标题】:Pipe string, file contents, string into sqlite without intermediate file?管道字符串,文件内容,字符串到没有中间文件的sqlite?
【发布时间】:2021-06-13 21:41:52
【问题描述】:

我有这个 shell 脚本,它接受一组 INSERT 语句并在开始时放置一个“BEGIN TRANSACTION”,在最后放置一个“COMMIT”。有 很多 个 INSERT 语句,因此插入速度更快。

我使用成功的脚本是这样的

file_name_improved_sql=foo-improved.sql
file_name_original_sql=foo.sql
file_name_sqlite_db=bar.db
path_to_insert_error=/tmp/fooerrors.log
#
echo 'BEGIN TRANSACTION;' | cat - $file_name_original_sql  > $file_name_improved_sql 
echo "COMMIT;" >> $file_name_improved_sql
#
cat $file_name_improved_sql | sqlite3 $file_name_sqlite_db 2> $path_to_insert_error

我想对此进行改进,以便直接通过管道输入两个字符串和文件内容,而不是生成中间文件 file_name_improved_sql

类似的东西(除了这个不起作用)......

export string1="BEGIN TRANSACTION"
export string2="COMMIT"
cat $string1 $file_name_improved_sql $string2 | sqlite3 $file_name_sqlite_db 2> $path_to_insert_error

如果有任何建议,将不胜感激。

【问题讨论】:

    标签: bash sqlite shell pipe


    【解决方案1】:

    任一组命令并将整个组重定向到管道到sqlite3

    {
      printf %s\\n 'BEGIN TRANSACTION;'
      cat "$file_name_original_sql"
      printf %s\\n 'COMMIT;'
    } | sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"
    

    要么使用 here-document 作为sqlite3 的输入:

    sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error" <<EOF
    BEGIN TRANSACTION
    $(cat "$file_name_original_sql")
    COMMIT;
    EOF
    

    或者使用printf 来组合通过管道传送到sqlite3 的元素:

    printf 'BEGIN TRANSACTION;\n%sCOMMIT;\n' "$(cat "$file_name_original_sql")" |
      sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"
    

    或者创建一个函数来将一个 SQL 输入流构建到一个事务中:

    sql_transaction() {
      printf %s\\n 'BEGIN TRANSACTION;'
      cat
      printf %s\\n 'COMMIT;'
    }
    
    sql_transaction <"$file_name_original_sql" |
      sqlite3 "$file_name_sqlite_db" 2> "$path_to_insert_error"
    

    【讨论】:

    • 谢谢。 'printf' 方法是我使用的一种方法,它很好地结合了“它有效”和易于理解正在发生的事情。
    【解决方案2】:

    sqlite3 shell 中的.read 命令采用文件名来读取命令。如果该名称以管道字符开头,则将其视为 shell 命令而不是文件名,并从该命令的标准输出中读取。

    所以你可以做类似的事情

    sqlite3 "$file_name_sqlite_db" ".read '|echo \"BEGIN TRANSACTION;\"; cat \"file_name_original_sql\"; echo \"COMMIT;\"'"
    

    改用heredoc有助于简化引用:

    sqlite3 "$file_name_sqlite.db" <<EOF
    .read '|echo "BEGIN TRANSACTION;"; cat "$file_name_original.sql"; echo "COMMIT;"'
    EOF
    

    【讨论】:

    • 对于这种情况,另一个答案更好,但留下这个答案是因为从管道技巧中读取的内容并不为人所知。
    • 感谢您的回答。和你一样,我认为@LeaGris 更适合我目前的需求,但感谢你的回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 2011-05-06
    • 2019-02-02
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多