Bash

在單引號子命令中轉義單引號,本身在雙引號命令中

  • September 24, 2021

問題很簡單如下:

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 呼叫所需的雙引號內。

如何解決這個問題?通過使用或使用多個雙/單引號來轉義這些單引號,

我幾乎看到了所有可能的語法錯誤。\

您不能在單引號內轉義單引號。但是,您可以使用以下方法偽造它:

'\''

解釋:這是一個結束單引號(即結束目前引用),後跟一個轉義單引號,然後再次開始單引號。它的工作原理與'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 DBI中(我沒有包含任何樣板登錄內容,只是帶有準備好的語句和占位符的選擇):

# 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 '...' {} +命令和許多其他必須嵌套多級引號的情況下,您將遇到與嵌套引號相同的問題。

引用自:https://unix.stackexchange.com/questions/670305