76

我很好奇为什么在将 IFS 设置为像这样在换行符上拆分时需要退格:

IFS=$(echo -en "\n\b")

为什么我不能只使用它(这不起作用)呢?

IFS=$(echo -en "\n")

我在使用 Unix 行结尾保存文件的 Linux 系统上。我已经将带有换行符的文件转换为十六进制,它肯定只使用“0a”作为换行符。

我用谷歌搜索了很多,虽然很多页面都记录了换行符后跟退格的解决方案,但我发现没有一个可以解释为什么需要退格。

-大卫。

4

5 回答 5

140

因为正如 bash 手册所说的关于命令替换

Bash 通过执行命令并将命令替换替换为命令的标准输出来执行扩展,并删除任何尾随的换行符。

因此,通过添加\b您可以防止删除\n.

一种更简洁的方法是使用$''引用,如下所示:

IFS=$'\n'
于 2013-05-30T08:51:17.283 回答
59

我只记得最简单的方法。在 debian wheezy 上使用 bash 进行测试。

IFS="
"

不开玩笑:)

于 2013-11-06T21:15:38.587 回答
12

由于使用echo和命令替换,这是一个 hack。

prompt> x=$(echo -en "\n")
prompt> echo ${#x}
0
prompt> x=$(echo -en "\n\b")
prompt> echo ${#x}
2

去除$()尾随换行符并\b防止\n成为尾随换行符,同时极不可能出现在任何文本中。IFS=$'\n'是将 IFS 设置为在换行符上拆分的更好方法。

于 2013-05-30T09:07:26.703 回答
5

由于删除了命令替换中的拖尾,因此添加\b了作为换行符后缀的字符。所以 the被用作 的后缀,并且 by that不再是尾随,所以它从命令替换中返回。\n\n$(...)\b\n\n

副作用是,这IFS也将包括\bchar 作为分隔符,而不是 just \n,这确实是我们唯一感兴趣的。

如果您期望\b有一天可能会出现在字符串中(为什么不呢?),那么您可以使用:

IFS="$(printf '\nx')" && IFS="${IFS%x}";

returns \n suffixed with x && removes x

现在 IFS 只包含\n字符。

IFS="$(printf '\nx')" && IFS="${IFS%x}";
echo ${#IFS}; # 1

\b在, 测试的情况下什么都不会破坏:

#!/bin/sh

sentence=$(printf "Foo\nBar\tBaz Maz\bTaz");
IFS="$(printf '\nx')" && IFS="${IFS%x}";

for entry in $sentence
do
    printf "Entry: ${entry}.\n";
done

给出两行(由于一个\n):

Entry: Foo.
Entry: Bar      Baz Maz Taz.

正如预期的那样。

IFS="$(printf '\nx')" && IFS="${IFS%x}";使用:

IFS="
"

给出相同的结果,但是这两行不能缩进,如果您不小心在“和”之间放置了空格或制表符或任何其他白色字符,您将不再只有\n字符,还有一些“奖金” . 除非您在编辑器中使用“显示所有字符”选项,否则很难发现此错误。

于 2020-06-27T04:43:20.243 回答
0

只需按 enter 而不分配任何内容也可以。虽然,看起来有人犯了错误,难以理解。

IFS=
#This is a line
于 2016-05-22T20:29:45.367 回答