sed: insert a string after every N lines

前端 未结 6 2042
無奈伤痛
無奈伤痛 2021-01-31 03:55

I want to insert a string after every 30 lines in my large file. I\'m using mini-sed, which doesn\'t support ~ (tilde) range operator. I\'m looking for sed-only solution please.

相关标签:
6条回答
  • 2021-01-31 04:05

    Begin Edit

    The initial solution bellow needs as much memory in the hold space as the size of the N lines. This is a better solution that only keeps '\n' in the hold space instead of all the lines, needing much less memory:

    sed -e 'p;G;s/[^\n]//g;t next;:next;s/^\n\{5\}$//;t insert;h;d;:insert;x;s/^.*$/new line/' your_large_file
    

    The same can be done using the i command that is less known than the s command:

    sed -e 'p;G;s/[^\n]//g;t next;:next;s/^\n\{5\}$//;t insert;h;d;:insert;x;i \
    new line
    d' your_large_file
    

    Again, the explained version that can be run with 'sed -f script your_large_file':

    # Whatever happen afterward, the current line need to be printed.
    p
    # Append the hold space, that contains as much \n as the number of lines read since the text has been added.
    G
    # Keeps only the \n in the pattern space.
    s/[^\n]//g
    # The 't next' bellow is needed so the 't insert' will not take into account the s command above.
    t next
    :next
    # If we have exaclty 5 \n in the patern space, empty the hold space and insert the text, else save the pattern space for next cycle.
    # In both cases, end the current cycle without printing the pattern space.
    s/^\n\{3\}$//
    t insert
    h
    d
    :insert
    x
    i \
    new line
    d
    

    End Edit

    The following script will add '\nnew line' after each 5 lines. If you want to do it every 6 or 100 lines, just change the '\{5\}' by '\{6\}' or '\{100\}'.

    sed -n -e 'H;g;s/[^\n]//g;t next;:next;s/^\n\{5\}$//;t insert;$ {x;s/^\n//;p};b;:insert;x;s/$/\nnew line/;s/^\n//;p' your_large_file
    

    This deserves some explanations, so bellow is a commented script file version . It must be run with 'sed -n -f script your_large_file'.

    H
    g
    # Now, the pattern and hold space contain what has been read so far with an extra \n at the beginning.
    s/[^\n]//g
    # Now, the pattern space only contains \n, the hold space is unmodified.
    # The 't next' bellow is needed so the 't insert' will not take into account the s command above.
    t next
    :next
    # If we have exactly 5 new lines in the pattern space, the hold space is printed without the \n at the beginning and with the text to added after 5 lines at its end.
    s/^\n\{5\}$//
    t insert
    # If not 5 \n and at the last line, the hold space must be printed without the \n at its beginning.
    $ {x;s/^\n//;p}
    b
    :insert
    x
    # Now the hold space is empty and ready to receive new lines as the pattern space has been emptied by the 2 s commands above.
    s/$/\nnew line/
    s/^\n//
    p
    
    0 讨论(0)
  • 2021-01-31 04:11

    This thread is another example of how to over complicate things. This should do it:

    sed '0~30 s/$/string/g' < inputfile > outputfile
    

    Every 30 lines "string" is inserted at the end of the line. If you want a new line with the word "string" just use "\n string".

    0 讨论(0)
  • 2021-01-31 04:23

    This inserts a line after every 3 lines.

    [STEP 101] # cat insert.sed
    # add one more 'x' into the hold space
    x
    s/^/x/
    t reset_t_cond
    : reset_t_cond
    # check if there are 3 'x' chars now
    s/x\{3\}//
    x
    t insert
    b
    
    : insert
    a\
    INSERT HERE
    [STEP 102] # seq 10 | sed -f insert.sed
    1
    2
    3
    INSERT HERE
    4
    5
    6
    INSERT HERE
    7
    8
    9
    INSERT HERE
    10
    [STEP 103] #
    
    0 讨论(0)
  • 2021-01-31 04:27
    sed 'n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;s/$/\ 
    string/' filename
    
    0 讨论(0)
  • 2021-01-31 04:28

    This inserts a line every 3 lines;

    seq 1 10 | sed ': loop; n; n; a insert
    n; b loop'
    

    Producing

    1
    2
    3
    insert
    4
    5
    6
    insert
    7
    8
    9
    insert
    10
    

    adjust the number of n; commands before the a command accordingly

    0 讨论(0)
  • 2021-01-31 04:31

    Use

    sed '1~30 i everyThirtyLine' file.dat
    

    This is tested in Cygwin.

    0 讨论(0)
提交回复
热议问题