我有一个文本文件 test.txt,内容如下:
text1 text2
我想把文件的内容分配给一个 UNIX 变量,但是当我这样做的时候:
testvar=$(cat test.txt) echo $testvar
结果是:
而不是
有人能给我一个解决方案吗?
这是由于 内部磁场分离器变量包含换行符。
$ 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
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变量的文档将其拆分为单词:
bash
IFS
IFS: 内部字段分隔符,用于展开后的分词... 默认值是 <space><tab><newline>。
<space><tab><newline>
它指定在默认情况下,可以使用这三个字符中的任何一个将命令拆分为单个单词。之后,单词分隔符就没有了,剩下的只有单词列表。
结合 echo文档(bash内部命令) ,您将看到输出空格的原因:
Echo [-neE ][ arg... ] : 输出 arg,用空格分隔,后跟换行符。
当您使用 echo "$x"时,它会根据 bash强制整个 x变量成为一个 单身字,因此它不会被拆分。你可以看到:
echo "$x"
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变体显示了它的作用。
count
1 2 3
a b c d
然后我们用 x变量的两个变量来尝试。一个 没有引号显示有四个单词,"test","1","test"和 "2"。添加引号使其成为 一单词 "test 1\ntest 2"。
"test"
"1"
"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 变量也会包含换行。
envdir
参见 https://pypi.python.org/pypi/envdir
testvar=$(cat test.txt)正确地设置了变量。要显示这个包含新行字符的变量,只需添加双引号,例如。
testvar=$(cat test.txt)
下面是完整的例子:
$ printf "test1\ntest2" > test.txt $ testvar=$(<test.txt) $ grep testvar <(set) testvar=$'test1\ntest2' $ echo "$testvar" text1 text2 $ printf "%b" "$testvar" text1 text2