【发布时间】:2010-05-07 14:33:29
【问题描述】:
我有一个包含以下内容的文本文件 test.txt:
text1
text2
我想将文件的内容分配给一个 UNIX 变量,但是当我这样做时:
testvar=$(cat test.txt)
echo $testvar
结果是:
text1 text2
而不是
text1
text2
有人可以建议我解决这个问题吗?
【问题讨论】:
我有一个包含以下内容的文本文件 test.txt:
text1
text2
我想将文件的内容分配给一个 UNIX 变量,但是当我这样做时:
testvar=$(cat test.txt)
echo $testvar
结果是:
text1 text2
而不是
text1
text2
有人可以建议我解决这个问题吗?
【问题讨论】:
这个任务没有删除换行符,实际上是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 ...]:输出args,用空格隔开,后跟换行符。
当您使用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 3 和 a b c d 变体展示了它的作用。
然后我们尝试使用x 变量的两个变体。一个没有引号表示有四个词,"test"、"1"、"test"和"2"。添加引号使其一个单个单词"test 1\ntest 2"。
【讨论】:
这是由于 IFS (Internal Field Separator) 变量包含换行符。
$ 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 "$(IFS=''; cat text.txt)"
Bash -ge 4 具有内置的 mapfile,可以将标准输入中的行读取到数组变量中。
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
【讨论】:
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
【讨论】:
如果有人对另一个选项感兴趣:
content=( $(cat test.txt) )
a=0
while [ $a -le ${#content[@]} ]
do
echo ${content[$a]}
a=$[a+1]
done
【讨论】:
envdir 实用程序提供了一种简单的方法来执行此操作。 envdir 使用文件来表示环境变量,文件名映射到环境变量名,文件内容映射到环境变量值。如果文件内容包含换行符,则环境变量也将包含换行符。
【讨论】: