将内容文件放入带换行符的 unix 变量中

我有一个文本文件 test.txt,内容如下:

text1
text2

我想把文件的内容分配给一个 UNIX 变量,但是当我这样做的时候:

testvar=$(cat test.txt)
echo $testvar

结果是:

text1 text2

而不是

text1
text2

有人能给我一个解决方案吗?

142246 次浏览

这是由于 内部磁场分离器变量包含换行符。

$ cat xx1
1
2


$ A=`cat xx1`
$ echo $A
1 2


$ echo "|$IFS|"
|
|

一个解决方案是重置 IFS,使其不包含换行符,暂时 :

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

为了恢复 IFS 的这种可怕的变化:

IFS=$IFSBAK

赋值是 没有删除换行符,实际上是 echo在做这件事。您只需要在字符串周围加上引号,就可以维护这些换行符:

echo "$testvar"

这将给出你想要的结果:

pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2


pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2

用空格替换换行符的原因不是 完全相信echo命令有关,而是一些事情的组合。

当给定一个命令行时,bash根据 IFS变量的文档将其拆分为单词:

IFS: 内部字段分隔符,用于展开后的分词... 默认值是 <space><tab><newline>

它指定在默认情况下,可以使用这三个字符中的任何一个将命令拆分为单个单词。之后,单词分隔符就没有了,剩下的只有单词列表。

结合 echo文档(bash内部命令) ,您将看到输出空格的原因:

Echo [-neE ][ arg... ] : 输出 arg,用空格分隔,后跟换行符。

当您使用 echo "$x"时,它会根据 bash强制整个 x变量成为一个 单身字,因此它不会被拆分。你可以看到:

pax> function count {
...>    echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1

在这里,count函数只是打印出给出的参数数量。1 2 3a b c d变体显示了它的作用。

然后我们用 x变量的两个变量来尝试。一个 没有引号显示有四个单词,"test""1""test""2"。添加引号使其成为 单词 "test 1\ntest 2"

Bash-ge4内置了将标准输入中的行读取到数组变量中的映射文件。

help mapfile


mapfile < file.txt lines
printf "%s" "${lines[@]}"


mapfile -t < file.txt lines    # strip trailing newlines
printf "%s\n" "${lines[@]}"

参见:

Http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile

如果有人对另一个选择感兴趣:

content=( $(cat test.txt) )


a=0
while [ $a -le ${#content[@]} ]
do
echo ${content[$a]}
a=$[a+1]
done

envdir实用程序为此提供了一种简单的方法。envdir使用文件来表示环境变量,文件名映射到 env var 名称,文件内容映射到 env var 值。如果文件内容包含换行,那么 env 变量也会包含换行。

参见 https://pypi.python.org/pypi/envdir

testvar=$(cat test.txt)正确地设置了变量。要显示这个包含新行字符的变量,只需添加双引号,例如。

echo "$testvar"

下面是完整的例子:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2