Shell-Script

%c 格式化字元串在 shell 和 C 中顯示不同的行為

  • January 25, 2019

如果我用 C 寫了一行非常簡單的程式碼:

printf("Ascii char for %d is %c\n",65,65);

它只是列印A,因為 65 的 ascii 值對應於字元A。但是如果我在 shell 中使用相同的程式碼並編寫命令

printf "Ascii char for %d is %c\n" 65 65

它顯示輸出為Ascii char for 65 is 6。我期待與 C 語言相同的輸出,並且在邏輯上它也應該列印與給定的 ascii 程式碼對應的字元。

為什麼它在這些情況下表現出不同的行為?

接受一個字元串並列印該%c字元串的第一個字元。如果字元串是65,如您的範例中所示,那麼它將列印6

這是由實用程序的 POSIX 規範指定的printf

轉換說明符的參數c可以是包含零個或多個字節的字元串。如果它包含一個或多個字節,**則應寫入第一個字節,**並且應忽略任何其他字節。如果參數是空字元串,則未指定是否寫入任何內容或寫入空字節。

如果相應的轉換說明符是**,**b ,cs

$$ … $$

這意味著格式的參數%cC(其中一個小的正整數將被轉換為 a char)和在 shell(其中相同的整數仍然是一個包含多個數字字元的字元串)中被解釋不同。不過,格式本身也做同樣的事情;它輸出單個字節作為字元。

然而:

$ printf '%d %b\n' 65 '\0101'
65 A

101 是八進制的 65。並且%b在 POSIX 中指定為

b應支持附加的轉換說明符字元 , ,如下所示。該參數應被視為可以包含<backslash>-escape 序列的字元串。

$$ … $$ \0ddd,其中ddd是一個零、一、二或三位數的八進制數,應將其轉換為具有八進制數指定的數值的字節。

它是一個附加的轉換說明符,因為它在標準 C 中不可用。但是在 shell 中需要它,因為我們沒有類型變數(在 POSIX shell 中)。

還:

$ printf '%d %b\n' 65 "$( printf '\\0%o\n' 65 )"
65 A

\0ddd在這裡,我們首先將 65 轉換為使用 格式的八進制數,然後再將其結果用於使用%o的另一個格式。printf``%b

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