问题很简单如下:
watch "psql -d postgresql://user:pass@host:5432/dbname -c 'select id,name from table where name <> 'not available' order by id;'"
这个'not available'
比较必须像Postgres 一样单引号。但是我无法找到正确转义这些单引号的方法,因为 psql 命令(我的意思是select...
)本身已经是单引号,并且也在psql
for watch 调用所需的双引号内。
如何解决这个问题?通过使用或使用多个双/单引号来转义这些单引号,
我几乎看到了所有可能的语法错误。\
您不能在单引号内转义单引号。但是,您可以使用以下方法伪造它:
解释:这是一个结束单引号(即结束当前引用),后跟一个转义单引号,然后再次开始单引号。它的工作原理与
'a'b'c'
(引用a
然后未引用然后b
引用c
- 所有在一起,这只是abc
......并且'a'\''b'
只是a'b
)(添加换行符以提高可读性。无论有没有它们,sql 命令的工作方式都相同)
注意:使用 postgres(或 sqlite 或 mysql 等)时,最好使用支持占位符的语言,因此您无需担心引用。他们的 CLI 非常适合交互式查询和一些脚本(在 SQL 中,而不是在 sh 中),但是从 sh 传递 sql 代码所需的嵌套引用很笨拙并且容易出错(并非不可能,只是比其他语言付出更多的努力)。
例如在 perl DBI中(我没有包含任何样板登录内容,只是带有准备好的语句和占位符的选择):
?
是一个占位符,DBI 将用您提供的任何值替换它 -如果需要,根据列的数据类型自动引用它。即只给它列的数据,让它担心引用和转义。顺便说一句,你可以有多个,你只需要以正确的顺序提供正确类型的参数。此外,一些 DBI 驱动程序 - 包括DBD::Pg - 允许您使用命名占位符
:name
或编号占位符,如$1
,$2
- 这些看起来相同,并且与 shell 位置参数大致相同,但它们不是,它们是占位符在 sql 语句中)对于不只是将数据和/或文件名输入其他程序并协调其他程序的执行的任何东西,shell 都是一种糟糕的语言。由于您必须对引用、空格、分词等问题付出的关心和关注,任何即使是中等复杂的东西都将成为 PITA。
ssh
在命令中或在find .. -exec sh -c '...' {} +
命令和许多其他必须嵌套多级引号的情况下,您将遇到与嵌套引号相同的问题。也可以使用heredoc并避免转义: