有条件地合并两条线

时间:2017-06-08 09:12:47

标签: bash awk

200005251|AAAAAA
200005252|BBBBB
200005261|CCCCCC
200005262|DDDDD
200005292|EEEEEE
200005301|FFFFFF
200005302|VVVVVV
200005311|AAAAAA
200005312|JJJJJJ
200006011|LLLLLL
200006021|SSSSSS
200006022|HHHHHH
200006051|OOOOOO
200006052|GGGGGG
200006061|KKKKKK
200006062|FFFFF
200006071|TTTTTT

我在第一个字段中有一个文件,如上所示。我需要合并每两行,如果他们只结束...... 1和...... 2。并按原样保留其他人。期望的输出:

200005251|AAAAAA 200005252|BBBBB  
200005261|CCCCCC 200005262|DDDDD    
200005292|EEEEEE  
200005301|FFFFFF 200005302|VVVVVV  
200005311|AAAAAA 200005312|JJJJJJ  
200006011|LLLLLL  
200006021|SSSSSS 200006022|HHHHHH  
200006051|OOOOOO 200006052|GGGGGG  
200006061|KKKKKK 200006062|FFFFF  
200006071|TTTTTT  

提前致谢。

4 个答案:

答案 0 :(得分:0)

Perl救援:

perl -nE 'chomp;
          if ($previous =~ /1$/ and /2$/) {
              say "$previous $_";
              $previous = "";
          } else {
              say $previous if $previous;
              $previous = $_;
          }
          }{ say $previous if $previous
         ' -- input

您将前一行保留在$ previous中。如果它以1结尾且当前行($_存储在-n中)以2结尾,则您在同一行打印它们并清除$ previous ;否则,如果有,则打印前一个,并将当前的一个存储在$ previous中。最后一行打印最后一个数字,如果它没有打印上一个数字。

答案 1 :(得分:0)

awk 解决方案:

awk -v RS=" " '{ for(i=1;i<=NF;i++) 
                    if ($i~/1$/ && $(i+1)~/2$/) { 
                        printf("%s %s\n",$i,$(i+1)); i++; 
                    } else { 
                        printf("%s\n",$i) 
                    } 
                }' file

输出:

200005251 200005252
200005261 200005262
200005292
200005301 200005302
200005311 200005312
200006011
200006021 200006022
200006051 200006052
200006061 200006062
200006071

正如您更改了初始输入 - 这是扩展版本:

awk -v RS=" " '{ for(i=1;i<=NF;i++) 
                     if ($i~/1\|[[:alpha:]]+$/ && $(i+1)~/2\|[[:alpha:]]+$/) { 
                         printf("%s %s\n",$i,$(i+1)); i++; 
                     } else { 
                         printf("%s\n",$i) 
                     } 
               }' file

输出v.2:

200005251|AAAAAA 200005252|BBBBB
200005261|CCCCCC 200005262|DDDDD
200005292|EEEEEE
200005301|FFFFFF 200005302|VVVVVV
200005311|AAAAAA 200005312|JJJJJJ
200006011|LLLLLL
200006021|SSSSSS 200006022|HHHHHH
200006051|OOOOOO 200006052|GGGGGG
200006061|KKKKKK 200006062|FFFFF
200006071|TTTTTT

详细

  • -v RS=" " - 将空格视为记录分隔符,而不是换行符

  • for(i=1;i<=NF;i++) - 遍历所有字段

  • if ($i~/1\|[[:alpha:]]+$/ && $(i+1)~/2\|[[:alpha:]]+$/) - 检查当前字段在其第1部分末尾是否有1且下一字段在其第1部分末尾有2的条件

答案 2 :(得分:0)

awk '{ num[NR]=$1 } END { for (i=1;i<=NR;i++) if (substr(num[i+1],length(num[i+1]))=="2") { printf num[i]"\t"num[i+1]"\n";i++ } else { print num[i] } }' nums

其中nums是包含数据的文件。首先,我们将数据放在一个名为num的数组中,然后我们遍历数组检查以查看下一个元素是否以两个结尾(使用substr函数和length来获取最后一个字符)。如果是,那么我们打印两个并向计数器添加一个,否则我们只打印元素。

答案 3 :(得分:0)

简单的awk脚本可以实现您的目标,

awk_file:

{
  if($1%2==1) {
    if(odd==1){
      printf "\n";
    }   
    printf "%s ",$0;
    odd=1;
  } else {
    printf "%s\n",$0;
    odd=0;
  }
} END {printf "\n"}

然后执行:

$ awk -v FS='|' -f awk_file file
200005251|AAAAAA 200005252|BBBBB
200005261|CCCCCC 200005262|DDDDD
200005292|EEEEEE
200005301|FFFFFF 200005302|VVVVVV
200005311|AAAAAA 200005312|JJJJJJ
200006011|LLLLLL 
200006021|SSSSSS 200006022|HHHHHH
200006051|OOOOOO 200006052|GGGGGG
200006061|KKKKKK 200006062|FFFFF
200006071|TTTTTT