使用不同的分隔符将分隔的字段移动到新行[再次更新]

时间:2014-04-10 06:13:49

标签: linux shell unix awk

我有逗号分隔的txt文件,该文件必须只有五列,但有些行的列数超过5列。
我想将第6到第10个移动到换行符,将第11个到第15个移到换行符等等。 并且6日,11日16日所以在列上有空格deleimert而不是逗号

以下是input.txt

的标准
111 1, 2, 3, 4, 5
11 2, 13, 14, 15 5, 16 11, 17, 18, 19, 20
22, 23, 24, 25, 26 22, 27, 28, 29, 21 30, 31, 32, 3333 3, 34

以下是Output.txt

的标准
111 1, 2, 3, 4, 5
11 2, 13, 14, 15 5, 16
11, 17, 18, 19, 20
22, 23, 24, 25, 26
22, 27, 28, 29, 21
30, 31, 32, 3333 3, 34

3 个答案:

答案 0 :(得分:1)

在这个问题的当前(第三个)版本中,看起来我们需要计算四个逗号,然后再计算一个实体,后跟一个空格(不是逗号),然后在该点添加换行符。如果是这种情况,请使用:

$ sed  's/\(\([^,]\+,\)\{4\}[[:space:]]\+[[:alnum:]]\+\)[[:space:]]/\1\n/g' input.txt
111 1, 2, 3, 4, 5
11 2, 13, 14, 15 5, 16
11, 17, 18, 19, 20
22, 23, 24, 25, 26
22, 27, 28, 29, 21
30, 31, 32, 3333 3, 34

如果sed支持-r标志(GNU),则命令的外观可以略微改进:

sed -r 's/(([^,]+,){4}[[:space:]]+[[:alnum:]]+)[[:space:]]/\1\n/g' input.txt

在OSX上,-r不支持-E标记:

sed -E 's/(([^,]+,){4}[[:space:]]+[[:alnum:]]+)[[:space:]]/\1\n/g' input.txt


此问题第二版的解决方案

从给出的示例中,我们需要在每次列以空格而不是逗号结束时插入换行符。如果是这种情况,那么:

$ sed 's/\>[[:space:]]/\n/g' input.txt
1, 2, 3, 4, 5
12, 13, 14, 15, 16
11, 17, 18, 19, 20
22, 23, 24, 25, 26
22, 27, 28, 29, 21
30, 31, 32, 33, 34

上述工作通过查找单词的结尾,sed\>表示,后跟任何类型的空格。然后用换行符替换该空格。用逗号代替的列将保持不变。

如果我们想要替换第一个匹配项,则sed替换命令的格式为s/old/new/,如果我们要替换所有此类匹配项,则s/old/new/gg替换命令的格式为\>[[:space:]]。由于我们希望所有匹配项都被替换,因此我们使用\n。在上面的命令中,“旧”部分是sed,这意味着单词结尾后跟任何类型的空格。 “新”部分只是sed -i 's/\>[[:space:]]/\n/g' input.txt ,代表换行符。

-i还允许选择更改文件:

sed

input.txt选项告诉{{1}}更改输入文件。运行此命令后,{{1}}将更新。

答案 1 :(得分:1)

尝试:

$ cat f1
1,2,3,4,5
12,13,14,15,16 11,17,18,19,20
22,23,24,25,26 22,27,28,29,21 30,31,32,33,34

$ awk '1' RS=' |\n' f1
1,2,3,4,5
12,13,14,15,16
11,17,18,19,20
22,23,24,25,26
22,27,28,29,21
30,31,32,33,34

用户更新输入解决方案

$ cat f2
1, 2, 3, 4, 5
12, 13, 14, 15, 16 11, 17, 18, 19, 20
22, 23, 24, 25, 26 22, 27, 28, 29, 21 30, 31, 32, 33, 34

$ awk '{gsub(/, /,",");gsub(/ /,"\n");gsub(/,/,", ")}1'  f2

OR

$ awk '{gsub(/[[:alnum:]] /,"&\n")}1' f2

1, 2, 3, 4, 5
12, 13, 14, 15, 16
11, 17, 18, 19, 20
22, 23, 24, 25, 26
22, 27, 28, 29, 21
30, 31, 32, 33, 34

回答以下评论

gsub(/, /,",")     # Substitute comma for comma + space

gsub(/ /,"\n")     # So now (field + space + field) is left, substitute space with newline  

gsub(/,/,", ")     # substitute comma space (as you requested in expected output) for comma (first argument)

答案 2 :(得分:0)

我没有时间将下面的脚本从ksh转换为bash,我把它留作练习:

#!/bin/ksh
splitline() {
   echo $* | IFS=\, read f1 f2 f3 f4 f5
   # remove first space
   fx=${f5# }
   echo ${fx} | read f5a f5b
   echo "${f1},${f2},${f3},${f4}, ${f5a}"
   if [[ -n "${f5b}" ]]; then
      splitline ${f5b}
   fi
}

cat input.txt | while read line; do
   splitline $line
done