tr 指令在 $() 中使用並保存在變數中時無效

tr 指令在 $() 中使用並保存在變數中時無效

如果我在 CLI 中運行:

curl time.com | sed -n 's/.*href="\([^"]*\).*/\1/p' | tr " " "\n"

然後,正如預期的那樣,我得到了從頁面到 的經過清理的連結列表STDOUT,每個連結都在新行上。

但是,當我將其保存到變數並嘗試echo從 a 中進行操作時script.sh

PAGE_LINKS=$(curl time.com | sed -n 's/.*href="\([^"]*\).*/\1/p' | tr " " "\n")
echo $PAGE_LINKS

我將所有連結放在一行上,以空格分隔。就好像tr被忽略了一樣。

我嘗試了多種方法,包括類似的方法

HREFS=$(tr " " "\n" < "{PAGE_LINKS}")
echo $HREFS

但後來我得到了file too long錯誤。有什麼建議麼?

答案1

根據構造bash的手冊頁$(command)

Bash 透過執行命令並將命令替換替換為命令的標準輸出來執行擴展,並刪除所有尾隨換行符。嵌入的換行符不會被刪除,但它們可能會在分詞過程中被刪除。

所以這tr不是問題,而是bash刪除尾隨的換行符,並在分詞期間刪除任何其他換行符。這是記錄的行為。

我相信您在大多數地方都希望這種行為。如果您有一個包含文件名稱清單的文件,則:

for FILENAME in $(cat somefile)
do
     ...
done

迭代檔案名稱列表。您不希望換行符somefile弄亂用作文件名的單字列表,甚至可能弄亂您的 for-do-done 循環。

答案2

問題不在於tr,問題在於如何輸出變數擴展:

echo $PAGE_LINKS

引用變數擴充:

echo "$PAGE_LINKS"

IFS否則擴充將根據(預設為空格、製表符、換行符)和路徑名擴展(*, ?, )的值進行分詞[]

在您的情況下,正在發生分詞,並且每個換行符分隔的元素都被單獨獲取,並最終顯示為空格分隔的實體。使用引號將防止分詞(和路徑名擴展),因此整個擴展將被視為單一實體。

相關內容