使用shell脚本将txt转换为csv(包含空白)

时间:2017-07-11 00:03:24

标签: string shell csv parsing

如何使用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

7 个答案:

答案 0 :(得分:0)

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个空格更改为&#39;,&#39;然后这个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添加一个逗号&#39;,&#39;然后取第二个保存的值\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

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

答案 1 :(得分:0)

您可以在POSIX shell中使用for ($i=1; $i<=$total_pages; $i++) { echo "<a href='index.php?page=".$i."' class=\"textPagina\">".$i."</a>&nbsp;&nbsp;"; } 执行您正在尝试的操作。基本上,只需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

请告诉我这是否适合您。

对于允许从子shell重定向的高级shell(例如bash),您可以使用$ 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 paste以及cut,例如

sed

答案 2 :(得分:0)

您可以尝试使用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<NF;i++):解析每个记录中用空格分隔的每个字段
  • printf "%s%s",$i,i<5?",":" ":如果:则打印i<5,否则打印" "

答案 3 :(得分:0)

awk -v FIELDWIDTHS='10 2 2 2' 'gsub(" +",",",$1)' file

答案 4 :(得分:0)

  1. pastecuttr&amp; 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
    

答案 5 :(得分:0)

只是为了增加乐趣:

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

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循环当然可以采用输入重定向。

答案 6 :(得分:0)

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

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