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否则扩展将根据(默认为空格、制表符、换行符)和路径名扩展(*, ?, )的值进行分词[]

在您的情况下,正在发生分词,并且每个换行符分隔的元素都被单独获取,并最终显示为空格分隔的实体。使用引号将防止分词(和路径名扩展),因此整个扩展将被视为单个实体。

相关内容