Cygwin bash 命令列中的非 ascii 導致錯誤

Cygwin bash 命令列中的非 ascii 導致錯誤

我像這樣從 cmd.exe 呼叫 bash

c:\cygwin\bin\bash --login -c "echo ф"

並取得 Cygwin 2.8.0

/usr/bin/bash: echo ф: command not found

它將參數視為命令名稱的一部分。在 Cygwin 2.5.2 上做同樣的事情我得到輸出ф

答案1

由於這曾經有效,並且對於在 Unices 上運行 bash 的人來說工作得很好(我在這裡在 Debian 上進行了測試),我認為您已經發現了 Cygwin 錯誤。 Cygwin 專案有一個關於報告 Cygwin 錯誤。他們那裡有很多有用的信息和步驟,太長了,無法在這裡總結。

同時,我懷疑你可以透過逃避角色來解決這個問題。 Bash 的echo,當給定-e標誌時,解釋各種轉義序列:

c:\cygwin\bin\bash --login -c "echo -e '\xd1\x84'"

應該管用。十六進位D1 84是 ф 的 UTF-8 編碼。如果您有該unicode工具,它會告訴您,但只會將字元回顯為odor xxd

$ echo -n 'ф' | od -t x1
0000000 d1 84
0000002

$ echo -n 'ф' | xxd -p
d184

Cygwin FAQ 告訴我它預設使用 UTF-8,所以應該可以工作。但當然你也可以使用其他編碼(我認為Windows大多使用UTF16le):

$ echo -n 'ф' | iconv -t utf16le | xxd -p
4404

答案2

發生這種情況是因為cmd.exe在帶有非 ASCII 字元的參數周圍添加了一對額外的引號。那麼實際到達 cygwin 應用程式的內容如下:

C:\cygwin\bin\bash --login -c "echo blo"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: echo blo

所以 bash 可以解釋 ' echo blo',但是:

C:\cygwin\bin\bash --login -c "echo blöd"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: "echo blöd"

現在 bash 無法辨識 ' "echo blöd"'。

答案3

使用者1274247的分析是正確的。

因此,當 cmd.exe 在我們不知情的情況下將它們加倍時,我們需要找到一種方法來去除前導和尾隨引號。

在處理包含空格、單引號和非 ASCII 字元的路徑時,我遇到了完全相同的問題。我透過分離要執行的 bash 命令(又名-c)和有問題的字串參數來解決這個問題。

根據 bash 人的說法:

-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0. 

因此我們的命令變成:

C:\cygwin\bin\bash.exe -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"

或者,如果您喜歡使用 mintty 終端機:

C:\cygwin\bin\mintty.exe /bin/bash -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"

如果你想在 regedit 中使用它(右鍵單擊檔案時啟動 bash 命令),這裡是正確的轉義(對於引號和 %):

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\*\shell\Test]
@="echo filename in bash"

[HKEY_CURRENT_USER\Software\Classes\*\shell\Test\command]
@="C:\\cygwin\\bin\\mintty.exe /bin/bash -lc ' a=\"${0%%\\\"}\"; a=\"${a#\\\"}\";echo \"$a\"; sleep 10 ' \"%1\""

例如,我使用它來複製文件(從更大的工具箱中提取):

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate]
@="Duplicate file"

[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate\command]
@="C:\\cygwin\\bin\\mintty.exe /bin/bash -lc ' a=\"${0%%\\\"}\"; a=\"${a#\\\"}\" ; cd \"$(dirname \"$(cygpath \"$a\")\")\"; f=\"$(basename \"$a\")\" ; n=\"$(basename \"$a\" \".${f##*.}\")\" ; cp \"${f}\" \"${n}-copy.${f##*.}\"   ' \"%1\" "

相關內容