【问题标题】:Joining Line Breaks With Condition in SED在 SED 中加入有条件的换行符
【发布时间】:2009-09-29 04:56:11
【问题描述】:

我的数据如下所示:

> sq1
foofoofoobar
foofoofoo
> sq2
quxquxquxbar
quxquxquxbar
quxx
> sq3
foofoofoobar
foofoofoo
> sq4
foofoofoobar
foofoo

我想在“>sqi”标题的基础上加入线条作为分界线, 即屈服:

foofoofoobarfoofoofoo
quxquxquxbarquxquxquxbarquxx
foofoofoobarfoofoofoo
foofoofoobarfoofoo

我尝试使用这个sed 但失败了:

sed '/^S/d;N;s/\n/\t/' 

正确的做法是什么?

【问题讨论】:

    标签: linux bash unix sed


    【解决方案1】:
    #!/bin/sed -f
    
    # If this is a header line, empty it...
    s/^>.*//
    # ... and then jump to the 'end' label.
    t end
    # Otherwise, append this data line to the hold space.
    H
    # If this is not the last line, continue to the next line.
    $!d
    # Otherwise, this is the end of the file or the start of a header.
    : end
    # Call up the data lines we last saw (putting the empty line in the hold).
    x
    # If we haven't seen any data lines recently, continue to the next line.
    /^$/d
    # Otherwise, strip the newlines and print.
    s/\n//g
    
    # The one-line version:
    # sed -e 's/^>.*//;te' -e 'H;$!d;:e' -e 'x;/^$/d;s/\n//g'
    

    【讨论】:

      【解决方案2】:

      原始问题的 bash 解决方案(即没有“标题”):

      #!/bin/bash
      text=[]
      i=0
      
      exec <$1
      
      while read line
      do
          text[$i]=$line
          let "i += 1"
      done
      
      
      j=0
      len=0
      while [ $j -lt ${#text[@]} ]
      do
          string=${text[$j]}
          if [ $len -le ${#string} ] ; then
              printf $string
          else
              printf $string'\n'
          fi
          len=${#string}
          let "j += 1"
      done
      printf '\n'
      

      【讨论】:

        【解决方案3】:

        我在 sed 中找不到简单的方法。无论如何,使用 gawk/mawk 你只需要改变 RS 变量并剪切换行符:

        awk -v RS='> sq[0-9]' 'NR>1{gsub(/\n/,"");print}' file
        

        【讨论】:

          【解决方案4】:

          您正在测试行首的大写“S”。您应该测试大于字符:

          sed '/^>/d;N;s/\n/\t/'
          

          sed '/^> sq/d;N;s/\n/\t/'
          

          编辑:我错过了标题之间的行数可变的事实。这是我目前所拥有的:

          sed  -n '/^>/{x; p; d}; /^>/!H; x; s/\n/\t/; h; $p'
          

          不幸的是,这留在了标题中:

          > sq1    foofoofoobar    foofoofoo
          > sq2    quxquxquxbar    quxquxquxbar    quxx
          > sq3    foofoofoobar    foofoofoo
          > sq4    foofoofoobar    foofoo
          

          如果您在 Bash 提示符下执行此操作,您可能必须先执行 set +H,这样您就不会因为感叹号而受到历史扩展干扰。

          Edit2:我的修改版去掉了标题:

          sed  -n '1{x;d};/^>/{x; p; d}; H; x; s/\n/\t/; s/^>.*\t//; h; $p'
          

          【讨论】:

          • @DW:你的 sn-p 似乎不起作用。我得到了“foofoofoobartfoofoofoo \n quxquxquxbartquxquxquxbar \n quxxt> sq3\n foofoofoobartfoofoofoo \n foofoofoobartfoofoo”
          猜你喜欢
          • 2019-12-01
          • 2011-01-22
          • 1970-01-01
          • 1970-01-01
          • 2011-08-31
          • 2011-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多