Home  >  Q&A  >  body text

linux - shell怎么多行并作一行处理?

如果第1行和第2行都不以;开头,则合并这两行为新行,并继续处理新行和第3行;
如果第1行以;开头,则继续处理第2行和第3行。
以上流程仅为方便描述,只要能达到相同效果即可。
如输入为:
;a
;;b
c
d;
e;;;
;f
g
期望输出:
;a
;;b
cd;e;;;
;f
g

PHPzPHPz2743 days ago821

reply all(4)I'll reply

  • 大家讲道理

    大家讲道理2017-04-17 12:07:30

    Answer

    awk '!/^;/{a=arrreee}/^;/{if(a!="")print a;print rrreee;a="";}END{if(a!="")print a;}'
    

    Explanation

    awk syntax test1{statements1}test2{statements2}...

    For 每一行, if test1 is satisfied, statement1 is executed, and if test2 is satisfied, statement2 is executed...

    So it is divided into 3 parts:

    • !/^;/{a=a;} If it does not start with a, append the current line to a temporary variable
      (as a buffer)
      • !/^;/

        • !
        • Negation
        • /.../
        • means testing whether the current line satisfies the given regular expression
        • ^; ; Regular expression, indicating
        • starting with
      • a=a

        • a
        • Variable, no need to declare, use it directly, the default value is 0, null, "", it will be automatically converted according to the usage scenario, the first time it is used here is the empty string
        • a
        • represents the entire line of content
      Two strings written together represent string concatenation
    • /^;/{if(a!="")print a;print ;;a="";} a

        If it starts with
      • , first output the temporarily spliced ​​variable /^;/ (if any), and then output the current line ;
      • if(a!="")print a;print
        ;a="";

        Determine whether the current line starts with
        • if(a!="")print a;
        • print
        • ;
        • a=""; a If a is not empty, output the value of a (print automatically wraps)
      • Print the current line
    • Clear the value of END{if(a!="")print a;} for next time use a

      • ; a After processing all lines, finally determine whether there is content in the buffer ;. If so, print
      • END BEGINIf the last few lines do not start with
      • , they will all be appended to
      , and there will never be a chance to output them, because
    • will be output only when the lines starting with
    are encountered. <🎜> The <🎜> condition means after processing the last line (the opposite is of course <🎜>, which means before processing the first line) <🎜> <🎜> <🎜> <🎜>

    reply
    0
  • PHP中文网

    PHP中文网2017-04-17 12:07:30

    First: Remove the line breaks, /n//g
    Then: Determine whether there are numbers on the right side of the letter sequence, if so, add a newline character /([a-z]+)(?=[0-9]+)/1/n/g
    on the right side Determine whether there are numbers on the left side of the letter sequence, if so, add a newline character /([a-z]+)(?<=[0-9]+)//n1/g
    to the left Finally: Use sed or awk to implement the above regular expression.

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-17 12:07:30

    awk version

    awk '
    sed -n '/^;/{H;x;s/^\n//g;p;s/.*//g;x;};/^;/!{H;x;s/\n//g;x};${/^;/!p}' urfile
    
    !~ /^;/{a=arrreee;}/^;/{print a?a"\n"rrreee:rrreee;a=""}END{if(a)print a}' urfile

    Add another sed

    rrreee

    reply
    0
  • PHPz

    PHPz2017-04-17 12:07:30

    This slightly complex requirement can be achieved using sed/awk, but I don’t think it is recommended. At this time, it is generally more efficient to use python or perl.

    However, in order to see if my sed skills are still there, I gave it a try. So far, no problem has been found in a simple test. The code is as follows:

    sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};x;s/\n//gp;g};p'
    

    Explain some important parts:
    1. h;s/.*//;x; is to clear the hold space
    2. The :l $!{H;n;/^;/!b l}; part is a loop that merges all lines not starting with ; into the hold space. There are two exit conditions: reaching the last line or encountering a line starting with ;
    3. x;s/n//gp;g Remove the line breaks from the content in the hold space and print it out
    4. Finally p prints the content in the pattern space, which is used to print the lines starting with ;

    I haven’t finished writing the answer yet, but I found a bug: If there are more than 2 lines at the end of the file that do not start with ;, the last line is not merged.

    Revise the original answer to:

    sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};/^;/!{H;g;s/\n//gp;t};x;s/\n//gp;g};p'
    

    Modification instructions:
    1. After jumping out of the loop, determine if the current line does not start with ; (according to the previous exit condition, this is the last line), add the current line to the hold space, and then process the content of the hold space

    Look, a requirement that is actually not very complicated is written using sed. The commands get longer and longer. Can you still understand it at a glance after a month? It’s better not to use sed for such needs

    reply
    0
  • Cancelreply