Bash 重定向不适用于 SQLite 命令

Bash 重定向不适用于 SQLite 命令

Bash 允许以这种方式从另一个命令管道到标准输入......

$ ls /bin/aud* | cat
/bin/audacity
/bin/audiocompose
/bin/audiosend
...

...还有这样的方式:

$ cat <(ls /bin/aud*)
/bin/audacity
/bin/audiocompose
/bin/audiosend
...

然而,当我尝试使用相同的模式向 SQLite 发送查询时,我从第一个表单中得到了这个......

$ echo "select count(*) from urls;" | \
    sqlite3 ~/.config/google-chrome/Default/History
5983

...但是第二个出现这个错误:

$ sqlite3 ~/.config/google-chrome/Default/History \
   <(echo "select count(*) from urls;")
Error: near "/": syntax error

这令人惊讶... SQL 语句没有被 shell 插入或弄乱:

$ echo "select count(*) from urls;"
echo "select count(*) from urls;"

这与两者无关echo- 它绝对可以用于重定向:

$ cat <(echo Foo)
Foo

我能想到的是,不知何故,数据库文件的路径被误解并作为 SQL 语句传入...(这是唯一包含“/”的地方 - “/ 附近的语法错误”的唯一解释)。

但为什么呢?有任何想法吗?

答案1

I/O 重定向的第二种形式 ( <(cmd)) 的行为方式与第一种形式 ( cmd | other-cmd) 不同。

第一个将 的输出连接cmd到 的输入other-cmd,但第二个替换路径/dev/fd命名管道命令的路径。的标准输出绑定到该管道的另一端,但这仅与从标准输入或文件路径读取的cmd命令等效。行为并非如此,因此它暴露了两种形式的 I/O 重定向之间的差异。catsqlite3

sqlite3 期望数据库路径后面是可选的 SQL 语句,因此它尝试将此替换路径解析为 SQL 并失败。

顺便说一句,这意味着您根本不需要 I/O 重定向。该命令比您尝试过的任何一种形式都更有效地完成您想要的操作:

$ sqlite3 ~/.config/google-chrome/Default/History "select count(*) from urls"

sqlite3请注意,在将单个 SQL 语句作为命令行参数传递时,不需要语句终止分号。

答案2

$ echo <(echo "hi")
/dev/fd/63

/dev/fd/63不是 SQL,因此sqlite3失败并显示指示的错误消息。cat相比之下,它非常擅长读取文件(或者也可以从标准输入读取)。创建的构造的命名管道或/dev/fd文件<(list)不是标准输入。

相关内容