【问题标题】:convert txt to csv using shell script (blank included)使用 shell 脚本将 txt 转换为 csv(包括空白)
【发布时间】:2017-07-11 00:03:24
【问题描述】:

如何使用 shell 脚本将 .txt 转换为 .csv ??
输入

A B 10 C d e f g
H I 88 J k l m n
O P 3  Q r s t u

预期输出 - 4 个空白后,不要更改为 ','

A,B,10,C,d e f g
H,I,88,J,k l m n
O,P,3,Q,r s t u

我正在尝试但无法处理“d e f g”

$ cat input.txt | tr -s '[:blank:]' ',' > output.txt

【问题讨论】:

    标签: string shell csv parsing


    【解决方案1】:

    sed -s 's/\s\{1,\}/,/g' input.txt > output.txt

    输入的输出是

    A,B,10,C,d,e,f,g
    H,I,88,J,k,l,m,n
    0,P,3,Q,r,s,t,u
    

    解释:

    sed -s 's/<searchText>/<replacetext>/<flags>'

    搜索文字\s\{1,\} \s 匹配任何空格 \{1,\} 匹配 1 个或多个连续字符。

    替换文本, - 替换为逗号

    标志g 替换给定行上的所有匹配项。

    编辑:

    你只想把前4个空格改成','然后这个sed

    sed -s 's/\(\S*\)\s*\(\S*\)\s*\(\S*\)\s*\(\S*\)\s*/\1,\2,\3,\4,/' input.txt > output.txt

    应该可以。

    解释:

    \(\S*\)\s* 重复 4 次。它首先匹配 \S* 所有非空白字符并保存值(因为 \(\) 围绕该字段。\s* 然后匹配所有空白字符。4 组 4 次。

    现在替换为\1,\2,\3,\4,。这意味着取第一个保存的值\1加一个逗号',然后取第二个保存的值\2等等。

    你得到的输出是:

    A,B,10,C,d e f g
    H,I,88,J,k l m n
    0,P,3,Q,r s t u
    

    您应该能够通过遵循该模式轻松修改替换的空格数。

    【讨论】:

    • 请再次检查我的预期结果..我不想在 4 个空白之后将空白更改为 ','..
    • 有什么决定你想停在哪个空白处还是总是第四个?是否总是有相同数量的空白?
    • 将每行前面的四个空格改为逗号。谢谢你的帮助。
    【解决方案2】:

    您可以在 POSIX shell 中使用 expr substr 执行您正在尝试的操作。基本上,只需 read 并将每一行拆分为第一个 10 字符和剩余字符,并在前 10 个字符上调用 sed,例如

    while read -r line; do 
        first=$(expr substr "$line" 1 10)
        second=$(expr substr "$line" 11 20)
        printf "%s%s\n" "$(echo "$first" | sed 's/[ ][ ]*/,/g')" "$second"
    done < file
    

    只需将其粘贴到控制台中即可进行测试,例如

    $ while read -r line; do
    >     first=$(expr substr "$line" 1 10)
    >     second=$(expr substr "$line" 11 20)
    >     printf "%s%s\n" "$(echo "$first" | sed 's/[ ][ ]*/,/g')" "$second"
    > done < file
    A,B,10,C,d e f g
    H,I,88,J,k l m n
    O,P,3,Q,r s t u
    

    让我知道这是否适合你。

    对于允许从子 shell 重定向的高级 shell(例如 bash),您可以使用 pastecut 以及 sed,例如

    $ paste -d ' ' <(cut -c -10 file | sed 's/[ ][ ]*/,/g') <(cut -c 12- file)
    A,B,10,C,d e f g
    H,I,88,J,k l m n
    O,P,3,Q,r s t u
    

    【讨论】:

      【解决方案3】:

      您可以尝试使用awk 命令:

      $ awk '{for (i=1;i<NF;i++)printf "%s%s",$i,i<5?",":" ";print $NF}' input > output
      
      $ cat output
      A,B,10,C,d e f g
      H,I,88,J,k l m n
      O,P,3,Q,r s t u
      

      简要说明,

      • for (i=1;i&lt;NF;i++):解析每条记录中以空格分隔的字段
      • printf "%s%s",$i,i&lt;5?",":" ":如果i&lt;5,则打印:,否则打印" "

      【讨论】:

        【解决方案4】:
        awk -v FIELDWIDTHS='10 2 2 2' 'gsub(" +",",",$1)' file
        

        【讨论】:

          【解决方案5】:
          1. paste, cut, tr & bash 方法:

            paste -d ' ' <(cut -d ' ' -f 1-5 file | tr ' ' ,) <(cut -d ' ' -f 6- file)
            

            或者,使用 GNU cut,就不需要 tr

            paste -d ' ' <(cut -d ' ' --output-delimiter , -f 1-5 file ) \
                         <(cut -d ' ' -f 6- file)
            
          2. Shell脚本方法:

            while IFS=" " read a b c d e ; do echo "$a,$b,$c,$d,$e" ; done < file
            

          【讨论】:

            【解决方案6】:

            只是为了增加乐趣:

            这会将行上的前五组一个或多个空格转换为逗号:

            awk '{for(i=1;i<=4;i++){sub(/ +/,",")}}1'
            

            或者如果必须保存字节,你可以有同样的效果不太清楚:

            awk '{for(i=1;i++<=4;sub(/ +/,","))}1'
            

            您也可以使用sed。如果您的 printf(或者您的 shell 是 bash,具有内置的 printf),您可以相信 printf 在输入多个数据操作数时会重复一种格式。

            sed -n -E -e "$(printf 's/(([^ ]+) +)/\\2,/%d;' {4..1})p"
            

            这使用-E 来表示 ERE 而不是 sed 的默认 BRE。盐调味。

            当然,我将添加另一个仅限 bash 的选项。这依赖于一个数组。

            while read -a arr; do printf "%s," "${arr[@]:0:4}"; echo "${arr[@]:4}"; done
            

            所有这些解决方案都可以在管道上使用。 awk 和 sed 解决方案可以直接指向一个文件,while 循环当然可以进行输入重定向。

            【讨论】:

              【解决方案7】:

              使用awk我们可以得到所需的o/p:

              awk -F " " '{ print $1","$2","$3","$4,$(NF-2)," ",$(NF-1)," ",$(NF) }' shell.txt > output.txt
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-01-31
                • 1970-01-01
                • 2016-09-21
                • 2021-05-29
                • 2020-06-13
                • 2016-05-29
                • 2021-11-14
                • 1970-01-01
                相关资源
                最近更新 更多