當列印包含換行符的變數時,為什麼最後一個換行符被刪除?

當列印包含換行符的變數時,為什麼最後一個換行符被刪除?

file.txt 的內容(沒有什麼奇怪的,POSIX 定義的文字檔)

iguana
gecko
anole

範例腳本:

#!/bin/sh

string="$(cat file.txt)"

printf '%s' "$string"

範例輸出:

[coolguy@somemachine ~]$ ./script.sh
iguana
gecko
anole[coolguy@somemachine ~]$

最後一個換行符號發生了什麼事?為什麼除了最後一個保留之外,所有的都是換行符號?如果已經有換行符,我們似乎不必使用 echo 來新增換行符。

答案1

這不是列印,而是命令替換。它被定義為這樣做。來自POSIX 描述

shell 應透過在子 shell 環境中執行命令並將命令替換替換為命令的標準輸出來擴展命令替換,刪除替換末尾的一個或多個 {newline} 字元的序列

請注意,它刪除了全部尾隨換行符,而不只是一個。

在常見的情況下,您可以使用命令替換來捕獲單行輸出,例如osrev=$(uname -r).這些實用程式通常會列印尾隨換行符,以方便使用者在命令列上使用。但在 shell 腳本中,您可能想要將該字串用作另一個字串的一部分,例如檔案名稱:filename=blahblah-$osrev.dat。在這種情況下,尾隨的換行符只會帶來麻煩。

當然,無論如何,普通文字echo都會添加最後的換行符。


如果您希望變數中的文件內容按原樣存在,則常見的解決方法是在命令替換中添加額外的字符,然後將其刪除:

printf "foo\nbar\n\n" > file
string=$(cat file; echo x)
string=${string%x}
printf '%q\n' "$string"

輸出$'foo\nbar\n\n',顯示兩個尾隨換行符。


根據您打算如何處理數據,可能還有其他方法。例如,如果您碰巧想逐行處理文件,則可以使用while read循環或 Bash 。mapfile

相關內容