remove new line if next line does not begin with a number

前端 未结 4 1726
没有蜡笔的小新
没有蜡笔的小新 2021-01-19 16:54

I have a file that is like

    1 test
    test

How can I remove the new line from the so the final output becomes:

1 test test

相关标签:
4条回答
  • 2021-01-19 17:41

    A solution using 'sed':

    Input file (infile):

    1 test
    test
    2 two 
    3 three
    4 four
    five 
    six
    7 seven
    eight
    9 nine
    

    'Sed' program (script.sed):

    /[0-9]\+/ {
            : a 
            N
            /\n[0-9]\+/ {
                    P
                    s/.*\n//
            }
            t a
    }
    
    y/\n/ /
    

    Execution:

    $ sed -f script.sed infile
    

    Output:

    1 test test
    2 two
    3 three
    4 four five 
    six
    7 seven eight
    9 nine
    
    0 讨论(0)
  • 2021-01-19 17:48

    You can be a bit smarter and print a new line before the line if it starts with a digit (except for the first line);

    awk 'BEGIN{ORS="";} NR==1 { print; next; } /^[[:digit:]]/ { print "\n"; print; next; } { print; }'
    

    The awk script:

    BEGIN { ORS=""; }                            # default: no newline between output records
    NR==1 { print; next; }                       # first line: print
    /^[[:digit:]]/ { print "\n"; print; next; }  # if starts with a digit: print newline before
    {print;}                                     # other lines (next; has not been called yet)
    
    0 讨论(0)
  • 2021-01-19 17:50

    That is pretty simple to accomplish with sed. Consider the file below

    $ cat numbered                      
    1 abc
    def
    ghi
    2 jkl
    mno
    3 pqr
    4 stu
    vxw
    

    The command sed '/^[0-9]/{N; s/\n/ /;}' numbered will do the trick:

    $ sed '/^[0-9]/{N; s/\n/ /;}' numbered
    1 abc def
    ghi
    2 jkl mno
    3 pqr 4 stu
    vxw
    

    How it works: first, it verifies if the current line does start with a digit:

    /^[0-9]/
    

    The /^[0-9]/ is an address and matches only lines which starts with a digit. Iff some line matches it, the the command following the address will be executed.

    In this case, this command is a {, which opens a function list. The function list will aggregate two or more commands as if they where only one. In this case, we have two commands in the function list. The first one is the N command:

    N
    

    This command appends a newline and the next line to the pattern space. The next line will not be considered anymore after the current cycle. The next command is s/// which replaces newlines by a space:

    s/\n/ /
    

    So, the newline appended by N will be replaced by a space. Then, we need just to close the function list with }. The result will be:

    /^[0-9]/{
        N
        s/\n/ /
    }
    

    Since I've put all commands in one line for brevity, the commands inside the function list should be separated by semicolons:

    /^[0-9]/{N;s/\n/ /;}
    

    Note that if a line starting by a digit follows another line starting by a digit, the following line will be joined to the previous one and the command will apply to it.

    0 讨论(0)
  • 2021-01-19 17:52

    This should do the trick:

    sed -n '$!{ 1{x;d}; H}; ${ H;x;s|\n\([^0-9]\)| \1|g;p}' inputfile
    

    Input:

    1 test1
    test1
    2 test2
    test2
    test2
    3 test3
    4 test4
    

    Output:

    1 test1 test1
    2 test2 test2 test2
    3 test3
    4 test4
    
    0 讨论(0)
提交回复
热议问题