Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move lines matching a pattern from one file to another

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

Example

let's say I want to cut all lines containg bar from file1 and paste it into newly created file2

Input:

file1

bla foo bla
bla bar bla
bla aaa bla
bla bar bla
bla foo bla

Desired output after processing:

file1

bla foo bla
bla aaa bla
bla foo bla

file2

bla bar bla
bla bar bla

What I have tried

grep creates desired file2 but doesn't modify file1

grep 'bar' file1 > file2

sed -i modifies desired file1 but doesn't create file2

sed -i '/bar/d' file1

If I execute both commands one after another, I get desired result. But here I am looking for a single line command out of curiosity and to make a script more concise.

Your help would be appreciated.

like image 438
jkshah Avatar asked Oct 19 '13 10:10

jkshah


People also ask

Which command is used to extract lines with matching pattern from a file?

Use grep to select lines from text files that match simple patterns. Use find to find files and directories whose names match simple patterns. Use the output of one command as the command-line argument(s) to another command.

How do I move a line from one file to another in Linux?

Use the mv command to move a file from one location to another. To move a file on a computer with a graphical interface, you open the folder where the file is currently located, and then open another window to the folder you want to move the file into.

What is pattern matching in Linux?

3.5. 8.1 Pattern Matching. Any character that appears in a pattern, other than the special pattern characters described below, matches itself. The NUL character may not occur in a pattern. A backslash escapes the following character; the escaping backslash is discarded when matching.

How do you find a pattern in a file?

The grep utility searches the given input files selecting lines which match one or more patterns. The type of patterns is controlled by the options specified. By default, a pattern matches an input line if any regular expression (RE) in the pattern matches the input line without its trailing newline.


2 Answers

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
like image 32
Birei Avatar answered Sep 22 '22 15:09

Birei


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.

like image 56
potong Avatar answered Sep 22 '22 15:09

potong