如果我在 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
否则扩展将根据(默认为空格、制表符、换行符)和路径名扩展(*
, ?
, )的值进行分词[]
。
在您的情况下,正在发生分词,并且每个换行符分隔的元素都被单独获取,并最终显示为空格分隔的实体。使用引号将防止分词(和路径名扩展),因此整个扩展将被视为单个实体。