Shell-Script

shell腳本沒有將空格作為參數分隔符(有人可以解釋一下那個小文件的區別嗎?)

  • October 31, 2022

短版(TL;DR)

我有 2 個小的單行文件,看似相同:

$ cat f1 f2
./cconv.sh 100 EUR USD
./cconv.sh 100 EUR USD

但它們不是,大小有 1 個字節的差異:

$ ls -l f1 f2
(...) 24 oct.  30 16:19 f1
(...) 23 oct.  30 16:19 f2

$ diff f1 f2
1c1
< ./cconv.sh 100 EUR USD
---
> ./cconv.sh 100 EUR USD

我曾經dhex計算出十六進制的差異。看起來 :

  • f1完成c2 a0 55 53 44 0a
  • f2完成 20 55 53 44 0a

有人知道這裡發生了什麼嗎?有什麼區別,更重要的是,它來自哪裡?這是包含 2 個文件的 zip 文件的連結,以及dhex結果的螢幕截圖。

長版(附加說明)

這 2 個文件摘自我的~/.bash_history file.

我注意到我的貝殼有一種非常奇怪的行為。採用以下非常基本的腳本:

#!/bin/sh
echo $#
echo "$1"
echo "$2"
echo "$3"
exit 0

在某些情況下(但哪些 ???),它不會將空格作為參數分隔符:

$ ./cconv.sh 100 EUR USD
2
100
EUR USD

但有時它會按預期工作:

$ ./cconv.sh 100 EUR USD
3
100
EUR
USD

它讓我發瘋!我花了幾個小時試圖弄清楚發生了什麼。以下是我為縮小範圍所做的一些測試:

  • 我在一台裝有 Debian 11、Gnome 3.38 的筆記型電腦上工作。但我碰巧也有一台作業系統完全相同的虛擬機(D11,G3.38),在虛擬機中一切正常。所以很明顯,我一定是對我的裸機筆記型電腦做了一些事情,讓它表現不佳。但是什麼???

  • 我注意到這個問題只發生在圖形會話中。如果我打開一個 tty (Ctrl+Alt+F n ),它工作正常

  • 我懷疑我的終端模擬器。但是在不同的模擬器中行為是相同的(我試過 Gnome Terminal、Terminator 和 Konsole,結果相同)

  • 我懷疑是貝殼。但是 Bash 或 Dash 的行為是相同的

  • 我禁用了我能想到的所有自定義:

    • 我暫時刪除了/etc/bashrc, /etc/profile,/etc/inputrc/etc/rc.local
    • 我暫時刪除了~/.bashrc~/.profile並且~/.inputrc
    • 我禁用了所有 Gnome Shell 的擴展
  • 我什至懷疑是鍵盤,並插入了 USB 鍵盤。結果相同。

我真的很困惑,不知道發生了什麼。我終於注意到 2 個命令之間的細微差別~/.bash_history:一個來自我的 Gnome 會話,另一個來自我的 tty 會話。顯然存在差異,但究竟是什麼,可能是什麼原因?

c2 a0不間斷空格字元的 UTF-8 編碼。它通常看起來像一個正常空格,但不被 shell 辨識為空格。

在一些鍵盤映射中,諸如 AltGr+Space 或 Option+Space 之類的東西會產生不間斷的空格。如果您的鍵盤映射在 AltGr 或 Option 後面也有例如豎線字元,這會很有趣,這樣可以更容易地鍵入|<nbsp>而不是|<sp>,給您這樣的錯誤:

$ echo foo | grep .
bash:  grep: command not found

(我認為 SE 會將 nbsp 折疊到正常空間,因此如果從此處複製粘貼,您可能不會收到錯誤消息。)

如果您從其他工具複製並粘貼參數,您可能會從那裡得到奇怪的格式,但這取決於程序。

有關不生成字元的一些解決方案,請參閱在 shell 中處理 nbsp字元。

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