【问题标题】:Unix how to concatenate lines based on patternUnix如何根据模式连接行
【发布时间】:2017-01-09 01:22:36
【问题描述】:

我想在一个文件中加入如下行。

输入

01EPH087362 SHHFHDH 3673
63737
Dhdhj
01EPH636363 DHHDH 
3637737
Hshshhd
01EPH7373838 HDJJDJ

输出

01EPH087362 SHHFHDH 3673 63737 Dhdhj
01EPH636363 DHHDH  3637737Hshshhd
01EPH7373838 HDJJDJ

我想要上面的输出;基本上每一行都应该以 01EPH 开头。

我有 awk 和 sed 但没有运气。知道的请帮忙。

【问题讨论】:

  • 在您的输出中,使用空格分隔连接的行是不一致的。

标签: unix awk


【解决方案1】:
$ awk '/^01EPH/{if (NR>1) print buf; buf=$0; next} {buf = buf OFS $0} END{print buf}' file
01EPH087362 SHHFHDH 3673 63737 Dhdhj
01EPH636363 DHHDH  3637737 Hshshhd
01EPH7373838 HDJJDJ

【讨论】:

    【解决方案2】:

    我的看法:

    awk '
        /^01EPH/ {printf "%s%s", nl, $0; nl = "\n"; next} 
        {printf " %s", $0} 
        END {print ""}
    ' file
    

    【讨论】:

      【解决方案3】:

      另一个awk

      $ $ awk 'NR>1 && /^01EPH/ {print ""} 
                                {printf "%s", $0 OFS} 
               END              {print ""}' file
      
      01EPH087362 SHHFHDH 3673 63737 Dhdhj
      01EPH636363 DHHDH  3637737 Hshshhd
      01EPH7373838 HDJJDJ
      

      模式匹配时添加换行符(第一行除外)和末尾,否则追加行...

      【讨论】:

        【解决方案4】:

        @suyog:您能否也尝试关注一下,如果这对您有帮助,请告诉我。

        awk '{printf("%s%s",($0 ~ /^01E/ && NR>1)?ORS:NR>1?FS:"",$0)} END{print ""}' Input_file
        

        输出如下。

        01EPH087362 SHHFHDH 3673 63737 Dhdhj                                                                                                                                           
        01EPH636363 DHHDH  3637737 Hshshhd                                                                                                                                             
        01EPH7373838 HDJJDJ
        

        【讨论】:

          【解决方案5】:

          输入

          $ cat f
          01EPH087362 SHHFHDH 3673
          63737
          Dhdhj
          01EPH636363 DHHDH 
          3637737
          Hshshhd
          01EPH7373838 HDJJDJ
          

          输出

          $ awk '(s=/^01EPH/) && NR>1{print ""}{printf("%s%s",(s?"":" "),$0)}END{print ""}' f
          01EPH087362 SHHFHDH 3673 63737 Dhdhj
          01EPH636363 DHHDH  3637737 Hshshhd
          01EPH7373838 HDJJDJ
          

          【讨论】:

            【解决方案6】:
            awk '/^01EPH/ { if (record != "") print record; record = ""; pad = "" }
                 { record = record pad $0; pad = " " }
                 END { if (record != "") print record }'
            

            如果以01EPH开头的行,打印保存的信息,如果有的话,清空保存的信息和padding。

            在每一行上,将填充和新行添加到保存的信息中;将焊盘设置为空白。

            最后,如果有任何内容,打印保存的记录。

            这甚至奇迹般地保留了DHHDH3637737Hshshhd 之间的双空格,因为在DHHDH 结尾的行上有一个尾随空格。

            输出:

            01EPH087362 SHHFHDH 3673 63737 Dhdhj
            01EPH636363 DHHDH  3637737 Hshshhd
            01EPH7373838 HDJJDJ
            

            【讨论】:

              【解决方案7】:

              当你的文件只有 \n 行结尾时,你可以使用

              sed 's/^01EPH/\r&/;$s/$/\r/' inputfile | tr -d "\n" | tr "\r" "\n"
              

              sed 的第一部分在每个01EPH 之前插入一个\r。第二部分在末尾附加一个,以便最后一行也以换行结束。 现在删除原始换行符并用换行符替换标记的换行符。
              它遍历文件 3 次,因此任何 awk 解决方案对于大文件都会更好,但我只想显示 trsed

              【讨论】:

                【解决方案8】:

                这里是纯 Bash(加上 printf),只是为了搞笑:

                while IFS= read -r line || [[ -n $line ]]; do 
                    if [[ "$line" =~ ^01EPH ]]; then
                        printf "%s%s" "$pad" "$line" 
                        pad=$'\n'
                    else
                        printf " %s" "$line"
                    fi
                done <file  
                

                这是一个 Perl slurp 解决方案:

                perl -0777 -ne 'while (/(^01EPH.*?)(?=^01EPH|\z)/gms) {($st=$1)=~s/\n/ /g; print "$st\n" }' file
                

                在这两种情况下,awk 可能更好...

                【讨论】:

                  【解决方案9】:

                  一个班轮:

                  tr '\n' ' ' < file.txt | sed s/01EPH/\\n01EPH/g
                  

                  tr '\n' ' ' &lt; file.txt - 生成一个字符串

                  sed s/01EPH/\\n01EPH/g - 在 01EPH 前加上换行符

                  【讨论】:

                  • 这将在每个 01EPH 之前插入换行符,即使它出现在一行中间的另一个字符串的中间。 tr 还删除了所有换行符,将其输出转换为非文本文件(根据 POSIX),因此任何给定的 sed 或任何其他工具对它的处理都是未定义的行为,因此 YMMV 使用它。最好的情况下,它还添加了一个前导换行符和一个尾随空白字符,并且不提供终止换行符,因此 YMMV 可以使用该输出进行操作。简而言之,不要这样做。
                  • 你是对的。无论如何,我会保留这个答案,以防万一。希望人们阅读 cmets:)
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-08-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-10-23
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多