Move lines matching a pattern from one file to another

后端 未结 5 1396
一向
一向 2021-02-12 23:09

I want to move lines matching certain pattern from file1 to file2. Analogous to operation cut and paste from one file to another in windows

相关标签:
5条回答
  • 2021-02-12 23:17

    I like the other answers, but just an (obvious) alternative approach in case you are worried about making a mistake in your pattern and want an easy way to rollback:

    grep    'bar' file1 > file2
    grep -v 'bar' file1 > file3
    

    Once you're happy with your results (hint: tee instead of > will allow you to see what's getting written to your files):

    mv file3 file1
    

    Generally I prefer perl to do substitution like in the above answer, but when the regex idiom gets too complicated and you are semi-blindly copying and pasting commands you don't understand, you're not in control of your precious data.

    0 讨论(0)
  • 2021-02-12 23:18

    This might work for you (GNU sed):

    sed -i -e '/bar/{w file2' -e 'd}' file1
    

    An alternative:

    sed -i -e '/bar/w file2' -e '//d' file1
    

    To append to file2, write to a temporary file and use cat to append at the end of file in a bash script, or use:

    sed -i -e '/bar/w tmpfile' -e '$e cat tmpfile >> file2 && rm tmpfile' -e '//d' file1
    

    N.B. For the last solution, only one input file can be modified at a time.

    0 讨论(0)
  • 2021-02-12 23:32

    You can use perl and select a different filehandle based in a match of a regular expression when printing:

    perl -i.bak -ne 'BEGIN { open $oh, q|>|, pop or die } { print { m/bar/ ? $oh : q|ARGVOUT| } $_ }' file1 file2
    

    It yields:

    ==> file1 <==
    bla foo bla
    bla aaa bla
    bla foo bla
    
    ==> file2 <==
    bla bar bla
    bla bar bla
    
    0 讨论(0)
  • 2021-02-12 23:40

    You can put a && between the two commands to make them a single line. But that won't be more readable, so I don't recommend you do that.

    To do the same in one command, you would need something that can edit a file in-place, removing lines you don't want and at the same time printing those lines to stdout or stderr so you could redirect it to the other file. Maybe ed can do this but I don't know how to write that. I don't think there is another "standard" UNIX tool to do this.

    Btw, cut & paste actually has 3 steps:

    1. Copy selected text to clipboard
    2. Remove from original file
    3. Paste from clipboard to new file

    The 2-step UNIX command does it without a clipboard.

    0 讨论(0)
  • 2021-02-12 23:44

    This awk script will do the trick:

    awk '{a[NR]=$0}END{for(i=1;i<=NR;i++)print a[i] > "file"(a[i]~/bar/?2:1)}' file1
    

    Outputs:

    $ cat file1
    bla foo bla
    bla aaa bla
    bla foo bla
    
    $ cat file2
    bla bar bla
    bla bar bla
    
    0 讨论(0)
提交回复
热议问题