【问题标题】:File content into unix variable with newlines使用换行符将文件内容放入 Unix 变量中
【发布时间】:2010-05-07 14:33:29
【问题描述】:

我有一个包含以下内容的文本文件 test.txt:

text1
text2 

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

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

结果是:

text1 text2

而不是

text1
text2 

有人可以建议我解决这个问题吗?

【问题讨论】:

    标签: bash unix


    【解决方案1】:

    这个任务没有删除换行符,实际上是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 3a b c d 变体展示了它的作用。

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

    【讨论】:

    • 引号......这就是我所缺少的!谢谢!
    • 另外值得注意的是:Trailing 换行符将被命令替换操作符本身删除:Try it online!
    【解决方案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)"
    【解决方案3】:

    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

    【讨论】:

      【解决方案4】:

      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
      

      【讨论】:

        【解决方案5】:

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

        content=( $(cat test.txt) )
        
        a=0
        while [ $a -le ${#content[@]} ]
        do
                echo ${content[$a]}
                a=$[a+1]
        done
        

        【讨论】:

          【解决方案6】:

          envdir 实用程序提供了一种简单的方法来执行此操作。 envdir 使用文件来表示环境变量,文件名映射到环境变量名,文件内容映射到环境变量值。如果文件内容包含换行符,则环境变量也将包含换行符。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-21
            • 1970-01-01
            • 2016-01-08
            • 2012-07-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多