在單引號子命令中轉義單引號,本身在雙引號命令中
問題很簡單如下:
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
)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 '...' {} +
命令和許多其他必須嵌套多級引號的情況下,您將遇到與嵌套引號相同的問題。