gpt4 book ai didi

bash - shell - temp IFS 仅作为换行符。为什么这不起作用 : IFS=$(echo -e '\n' )

转载 作者:行者123 更新时间:2023-11-29 08:59:22 31 4
gpt4 key购买 nike

我正在尝试在 shell 中使用 for 来迭代带空格的文件名。我读了 stackoverflow question IFS=$'\n' 可以使用并且似乎工作正常。然后我读了in a comment to one of the answers为了使其与 bash 以外的 shell 兼容,可以使用 IFS=$(echo -e '\n')

前者有效,后者无效。该评论被多次点赞。我检查了输出,变量似乎不包含换行符。

#!/bin/sh

IFS=$(echo -e '\n')
echo -n "$IFS" | od -t x1
for file in `printf 'one\ntwo two\nthree'`; do
echo "Found $file"
done

echo

IFS=$'\n'
echo -n "$IFS" | od -t x1
for file in `printf 'one\ntwo two\nthree'`; do
echo "Found $file"
done


输出显示第一个缺少字段分隔符:

0000000
Found one
two two
three


但是在第二个上是正确的:

0000000 0a
0000001
Found one
Found two two
Found three


我找到了一个已回答的问题,它可能与我的问题重复,也可能不重复:
linux - When setting IFS to split on newlines, why is it necessary to include a backspace? - Stack Overflow

IFS=$(echo -en '\n\b') 那里讨论的事情有任何危险吗?因为这会向 IFS 添加一个 \b (我检查过)。 \b 可以出现在文件名中吗?我不希望我的代码错误地拆分文件名。

对于如何在 for 循环后正确处理 IFS 的恢复,您还有什么建议吗?我应该将它存储在临时变量中,还是在子 shell 中运行 IFS 和 for 语句? (以及如何做到这一点?)谢谢

最佳答案

更新 - 将我的伪评论更改为真实答案。

我认为this answer应该解释你所看到的行为。特别是命令替换运算符 $() 和反引号将从命令输出中去除尾随换行符。但是,第二个示例中的直接赋值不会执行任何命令替换,因此可以按预期工作。

所以我不敢说我​​认为您提到的赞成评论是不正确的。


我认为恢复 IFS 最安全的方法是将其设置在子 shell 中。您需要做的就是将相关命令放在括号 () 中:

(
IFS=$'\n'
echo -n "$IFS" | od -t x1
for file in `printf 'one\ntwo two\nthree'`; do
echo "Found $file"
done
)

当然,调用子 shell 会产生小的延迟,因此如果要重复多次,则需要考虑性能。


顺便说一句,要非常小心,文件名可以同时包含\b 和\n。我认为它们不能包含的唯一字符是斜杠和\0。至少这就是它在这个 wikipedia article 上所说的.

$ touch $'12345\b67890'
$ touch "new
> line"
$ ls --show-control-chars
123467890 new
line
$

关于bash - shell - temp IFS 仅作为换行符。为什么这不起作用 : IFS=$(echo -e '\n' ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19190967/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com