【问题标题】:How to concatenate all lines from a file in Bash? [duplicate]如何在 Bash 中连接文件中的所有行? [复制]
【发布时间】:2011-12-22 05:23:42
【问题描述】:

我有一个文件csv

data1,data2,data2
data3,data4,data5
data6,data7,data8

我想将其转换为(包含在变量中):

variable=data1,data2,data2%0D%0Adata3,data4,data5%0D%0Adata6,data7,data8

我的尝试:

data=''
cat csv | while read line
do
data="${data}%0D%0A${line}"
done
echo $data  # Fails, since data remains empty (loop emulates a sub-shell and looses data)

请帮忙..

【问题讨论】:

    标签: bash shell loops while-loop


    【解决方案1】:

    从文件中删除换行符更简单:

    tr '\n' '' < yourfile.txt > concatfile.txt
    

    【讨论】:

    • tr '\n' '' &lt; csv 打印出值,就像您的原始脚本一样。如果你在 bash 的变量中不需要它——听起来像你这样做——你可以完全放弃它。
    • 对我来说不是“只是工作”,而是把我带到tr -d '\n',效果很好:谢谢!
    【解决方案2】:

    无用的猫,受到惩罚!您想将 CSV 输入到循环中

    while read line; do 
     # ...
    done < csv
    

    【讨论】:

    • 获得额外的空格:this,is,some,data%0D%0A this,is,again,data%0D%0A third,line,of,data%0D%0A Fourth,line,in ,数据%0D%0A
    • 有趣,我不知道。它们是在源文件中还是在您的 shell 表达式中?
    【解决方案3】:

    在 bash 中,

    data=$(
    while read line
    do
      echo -n "%0D%0A${line}"
    done < csv)
    

    在非 bash shell 中,您可以使用 `...` 代替 $(...)。此外,抑制换行符的echo -n 不幸的是不是完全可移植的,但这同样适用于 bash。

    【讨论】:

    • 获得额外的空格:this,is,some,data%0D%0A this,is,again,data%0D%0A third,line,of,data%0D%0A Fourth,line,in ,数据%0D%0A
    • 对...编辑添加echo -n
    • 仅供参考,$() 是标准的。已经好几年了。如果你想要一个便携的echo -n 使用printf
    【解决方案4】:
    awk 'END { print r }
    { r = r ? r OFS $0 : $0 }
      ' OFS='%0D%0A' infile  
    

    data=
    
    while IFS= read -r; do
      [ -n "$data" ] &&
         data=$data%0D%0A$REPLY ||
        data=$REPLY
    done < infile
    
    printf '%s\n' "$data"   
    

    最近的 bash 版本:

    data=
    
    while IFS= read -r; do
      [[ -n $data ]] &&
         data+=%0D%0A$REPLY ||
        data=$REPLY
    done < infile
    
    printf '%s\n' "$data"
    

    【讨论】:

      【解决方案5】:

      其中一些答案非常复杂。这个怎么样。

       data="$(xargs printf ',%s' < csv | cut -b 2-)"
      

       data="$(tr '\n' ',' < csv | cut -b 2-)"
      

      对你来说太“外用”了吗?

      IFS=$'\n', read -d'\0' -a data < csv
      

      现在你有了一个数组!随心所欲地输出它,也许用

      data="$(tr ' ' , <<<"${data[@]}")"
      

      还是太“外部效用”?很好,

      data="$(printf "${data[0]}" ; printf ',%s' "${data[@]:1:${#data}}")"
      

      是的,printf 可以是内置的。如果不是,但您的echo 是并且它支持-n,请改用echo -n

      data="$(echo -n "${data[0]}" ; for d in "${data[@]:1:${#data[@]}}" ; do echo -n ,"$d" ; done)"
      

      好吧,现在我承认我有点傻了。安德鲁的回答完全正确。

      【讨论】:

        【解决方案6】:

        另一个简短的 bash 解决方案

        variable=$(
          RS=""
          while read line; do
            printf "%s%s" "$RS" "$line"
            RS='%0D%0A'
          done < filename
        )
        

        【讨论】:

          【解决方案7】:

          我更喜欢循环:

          for line in $(cat file.txt); do echo -n $line; done
          

          注意:此解决方案要求输入文件在文件末尾有一个新行,否则它将删除最后一行。

          【讨论】:

          • @Julien,你可以在前面加上 "echo "" >> file.txt"
          • 并不总是可以修改源文件。您也可以使用临时副本。无论如何,您的解决方案是有效的;值得一提的是它的局限性或陷阱。
          【解决方案8】:

          一个非常简单的单行解决方案,不需要额外的文件,因为它很容易理解(我认为,只需将文件放在一起并执行 sed-replace):

          output=$(echo $(cat ./myFile.txt) | sed 's/ /%0D%0A/g')
          

          【讨论】:

            猜你喜欢
            • 2011-12-24
            • 2019-09-30
            • 2013-08-12
            • 2016-10-09
            • 1970-01-01
            • 1970-01-01
            • 2014-09-16
            • 2021-04-21
            • 1970-01-01
            相关资源
            最近更新 更多