将delimted字段移动到具有不同delimted的Newline中[再次更新]



我有一个逗号分隔的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

尝试:

$ 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)

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

$ sed  's/(([^,]+,){4}[[:space:]]+[[:alnum:]]+)[[:space:]]/1n/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:]]/1n/g' input.txt

在OSX上,-r标志不受-E的支持。应改为使用:

sed -E 's/(([^,]+,){4}[[:space:]]+[[:alnum:]]+)[[:space:]]/1n/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/g。由于我们希望替换所有出现的情况,因此我们使用g。在上面的命令中,"旧"部分是>[[:space:]],意思是单词末尾后跟任何类型的空格。"新"部分只是代表换行符的n

sed还允许选择更改您的文件:

sed -i 's/>[[:space:]]/n/g' input.txt

-i选项告诉sed就地更改输入文件。运行此命令后,input.txt将被更新。

我没有时间将下面的脚本从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

最新更新