簡體   English   中英

轉義參數中的雙引號

[英]Escape double quotes in parameter

在 Unix 中,我可以運行myscript '"test"'並得到"test"

在 Windows cmd我得到'test'

如何將雙引號作為參數傳遞? 我想知道如何從cmd窗口手動執行此操作,因此我不必編寫程序來測試我的程序。

我發現在某些地方使用的另一種轉義引號的方法(盡管可能不是可取的)是使用多個雙引號 為了讓其他人的代碼清晰易讀,我會解釋一下。

這是一組基本規則:

  1. 當不包含在雙引號組中時,空格分隔參數:
    program param1 param2 param 3將傳遞四個參數給program.exe
    param1param2param3
  2. 將參數傳遞給程序時,雙引號組會忽略空格作為值分隔符:
    program one two "three and more"將傳遞三個參數給program.exe
    onetwothree and more
  3. 現在解釋一些混淆:
  4. 直接出現在未用雙引號包裹的文本旁邊的雙引號組加入一個參數:
    hello"to the entire"world作為一個參數: helloto the entireworld
  5. 注意:上一條規則並不意味着兩個雙引號組可以直接相鄰出現。
  6. 緊跟在結束引號之后的任何雙引號都被視為(或作為)與雙引號組相鄰的普通解包文本,但只有一個雙引號:
    "Tim says, ""Hi!"""將作為一個參數: Tim says, "Hi!"

因此,存在三種不同類型的雙引號:打開的引號、關閉的引號和充當純文本的引號。
這是最后一個令人困惑的行的細分:

"   open double-quote group
T   inside ""s
i   inside ""s
m   inside ""s
    inside ""s - space doesn't separate
s   inside ""s
a   inside ""s
y   inside ""s
s   inside ""s
,   inside ""s
    inside ""s - space doesn't separate
"   close double-quoted group
"   quote directly follows closer - acts as plain unwrapped text: "
H   outside ""s - gets joined to previous adjacent group
i   outside ""s - ...
!   outside ""s - ...
"   open double-quote group
"   close double-quote group
"   quote directly follows closer - acts as plain unwrapped text: "

因此,文本有效地連接了四組字符(但是,一組沒有任何字符):
Tim says,是第一個,包裹着逃離空間
"Hi!是第二個,沒有包裹(沒有空格)
是第三個,一個不包含任何內容的雙引號組
"是第四個,展開的結束引號。

正如您所看到的,雙引號組仍然需要什么都不包裹,因為如果沒有它,下面的雙引號將打開一個雙引號組,而不是充當純文本。

由此,應該可以看出,因此,內外引號,三個雙引號充當純文本未轉義雙引號:

"Tim said to him, """What's been happening lately?""""

Tim said to him, "What's been happening lately?" 正如預期的那樣。 因此,始終可以可靠地將三個引號用作轉義符。
但是,在理解它時,您可能會注意到末尾的四個引號可以減少到僅僅兩個,因為它在技術上添加了另一個不必要的空雙引號組。

以下是一些關閉它的示例:

program a b                       REM sends (a) and (b)
program """a"""                   REM sends ("a")
program """a b"""                 REM sends ("a) and (b")
program """"Hello,""" Mike said." REM sends ("Hello," Mike said.)
program ""a""b""c""d""            REM sends (abcd) since the "" groups wrap nothing
program "hello to """quotes""     REM sends (hello to "quotes")
program """"hello world""         REM sends ("hello world")
program """hello" world""         REM sends ("hello world")
program """hello "world""         REM sends ("hello) and (world")
program "hello ""world"""         REM sends (hello "world")
program "hello """world""         REM sends (hello "world")

最后說明:我沒有從任何教程中閱讀任何內容 - 我通過實驗想出了所有內容。 因此,我的解釋在內部可能並不正確。 盡管如此,上面的所有示例都按照給定的方式進行評估,從而驗證(但不是證明)我的理論。

我僅使用帶有參數傳遞的 *.exe 調用(不是 *.bat,但我認為它的工作原理相同)在 64 位 Windows 7 上對此進行了測試。

嘗試這個:

myscript """test"""

"" 轉義到參數中的單個 "。

我無法快速重現這些症狀:如果我使用僅包含@echo.%1甚至@echo.%~1的批處理文件myscript.bat嘗試myscript '"test"' ,我會得到所有引號: '"test"'

也許您可以像這樣嘗試轉義字符^myscript '^"test^"'

Peter Mortensen 在他對 Codesmith 回答的評論中引用的第二份文件讓我更清楚地了解情況。 該文檔由 windowsinspired.com 編寫。 鏈接重復: 一個更好的方法來理解 Windows 命令行參數的引用和轉義

一些進一步的試驗和錯誤導致以下准則:

使用插入符號^轉義每個雙引號" 。如果您希望其他對 Windows 命令外殼具有特殊含義的字符(例如<>|& )被解釋為常規字符,那么也可以使用插入符號對它們進行轉義.

如果您希望您的程序foo接收命令行文本"a\\"bc" > d並將其輸出重定向到文件out.txt ,請按如下方式從 Windows 命令外殼啟動您的程序:

foo ^"a\^"b c^" ^> d > out.txt

如果foo\\"解釋為字面雙引號並期望未轉義的雙引號分隔包含空格的參數,則foo會將命令解釋為指定一個參數a"bc 、一個參數>和一個參數d

相反,如果foo將雙雙引號""解釋為文字雙引號,則將程序啟動為

foo ^"a^"^"b c^" ^> d > out.txt

引用文檔的關鍵見解是,對於 Windows 命令外殼,未轉義的雙引號會觸發兩種可能狀態之間的切換。

一些進一步的試驗和錯誤意味着在初始狀態下,重定向(到文件或管道)被識別並且插入符號^轉義雙引號並且插入符號從輸入中刪除。 在另一種狀態下,無法識別重定向並且插入符號不會轉義雙引號並且不會被刪除。 讓我們分別將這些狀態稱為“外部”和“內部”。

如果要重定向命令的輸出,則命令外殼在到達重定向時必須處於外部狀態,因此在重定向之前必須有偶數個未轉義(插入符號)的雙引號。 foo "a\\"b " > out.txt不起作用——命令外殼將整個"a\\"b " > out.txt作為其組合命令行參數傳遞給foo ,而不是只傳遞"a\\"b "並將輸出重定向到out.txt

foo "a\\^"b " > out.txt也不起作用,因為插入符號^是在內部狀態遇到的,它是普通字符而不是轉義字符,所以"a\\^"b " > out.txt被傳遞給foo

(希望)始終有效的唯一方法是將命令外殼始終保持在外部狀態,因為這樣重定向就起作用了。

如果您不需要重定向(或其他對命令 shell 具有特殊含義的字符),那么您可以不用插入符號。 如果foo\\"解釋為文字雙引號,那么您可以將其稱為

foo "a\"b c"

然后foo接收"a\\"bc"作為其組合參數文本,並且可以將其解釋為等於a"bc的單個參數。

現在 - 最后 - 到最初的問題。 從 Windows 命令外殼調用的myscript '"test"''"test"'傳遞給myscript 顯然myscript將單引號和雙引號解釋為參數分隔符並刪除它們。 您需要弄清楚myscript接受什么作為文字雙引號,然后在您的命令中指定它,使用^轉義任何對 Windows 命令外殼具有特殊含義的字符。 鑒於myscript在 Unix 上也可用,也許\\"可以解決問題。試試

myscript \^"test\^"

或者,如果您不需要重定向,

myscript \"test\"

我正在從 cmd 調用 powershell,並傳遞引號,這里沒有任何轉義。 在這個 Win 10 Surface Pro 上,重音可以避免雙引號。

>powershell.exe "echo la`"" >> test
>type test
la"

以下是我為其他字符轉義雙引號得到的輸出:

la\
la^
la
la~

使用另一個引號來轉義引號導致沒有引號。 如您所見,字符本身被輸入,但沒有轉義雙引號。

在Unix中,我可以運行myscript '"test"'然后得到"test"

在Windows cmd我得到'test'

如何傳遞雙引號作為參數? 我想知道如何從cmd窗口手動執行此操作,因此我不必編寫程序來測試程序。

也許您來到這里,因為您想知道如何在傳遞給/c on cmd.exe的命令中轉義所需的引號? 好吧,您不會:

CMD /c "MKDIR "foo bar""

將執行

MKDIR "foo bar"

這確實是我第一眼沒想到的行為。 一目了然的不一致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM