在单引号子命令内转义单引号,其本身在双引号命令内

在单引号子命令内转义单引号,其本身在双引号命令内

问题简单如下:

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...)本身已经是单引号,并且也在调用psqlfor watch 所需的双引号内。

怎么解决这个问题呢?我几乎通过使用或多个双/单引号来转义这些单引号
看到了所有可能的语法错误。\

答案1

您无法在单引号内转义单引号。但是,您可以使用以下方法来伪造它:

'\''

解释:这是一个结束单引号(即结束当前引用),后跟一个转义单引号,然后再次开始单引号。它的工作原理与'a'b'c'(引用a然后未引用b然后引用c- 全部在一起,这只是abc......并且'a'\''b'只是a'b)相同

watch "psql -d postgresql://user:pass@host:5432/dbname -c \
  'select id,name from table
   where name <> '\''not available'\''
   order by id;'"

(添加换行符是为了提高可读性。无论有没有换行符,sql 命令的工作方式都是一样的)


注意:当使用postgres(或sqlite或mysql等)时,最好使用支持占位符的语言,这样你就不需要担心引用。他们的 CLI 非常适合交互式查询和一些脚本编写(在 SQL 中,而不是 sh),但是从 sh 传递 sql 代码所需的嵌套引用很笨拙并且很容易出错(并非不可能,只是比其他语言要付出更多的努力) )。

例如在 Perl 中数据库接口(我没有包含任何样板登录内容,只是包含准备好的语句和占位符的选择):

# you could use string literals, but i'll use some
# variables for this example
my $exclude = 'not available';
my $sql = 'select id,name from table where name <> ? order by id';

my $sth = $dbh->prepare($sql);
$sth->execute($exclude);

?是一个占位符,DBI 会将其替换为您提供的任何值 - 引用它自动地如果需要,取决于列的数据类型。即只需给它列的数据,让它担心引用和转义。

顺便说一句,您可以有多个参数,您只需以正确的顺序提供正确类型的参数即可。另外,一些 DBI 驱动程序 - 包括DBD::Pg- 允许您使用命名占位符:name或编号占位符,例如$1, $2- 这些看起来相同,并且工作方式与 shell 位置参数大致相同,但它们不是,它们是 sql 语句中的占位符)

my $sql = 'select id,name from table where name <> $1 order by id';

shell 对于任何不仅仅是将数据和/或文件名输入到其他程序以及协调其他程序的执行的语言来说都是一种糟糕的语言。任何即使是中等复杂的东西都将成为 PITA,因为你必须注意引用、空格、分词等问题。在ssh命令中或在find .. -exec sh -c '...' {} +命令和许多其他必须嵌套多层引号的情况下,您将遇到与嵌套引号相同的问题。

答案2

也可以使用定界符并避免转义:

psql  "postgresql://[email protected]:5432/db1" <<EOF 
select id,name from table where name <> 'not available' order by id;
EOF

相关内容