1

I want to move lines from a text file into another text file. Those lines contain a word beginning with an underscore. This word is located on the sixth field of the lines; fields are separated with forward slashes. For example, move lines containing _Nokia on the sixth field, in the sample input file, below.

Apple/One-plus/Samsung/Mi/Sony/_Nokia/ Apple/One-plus/Samsung/Mi/Lenovo/_Nokia/ Apple/One-plus/Samsung/Mi/HTC/OPPO/ 

I have tried to move corresponding lines, with a regular expression, using grep, but it does not work.

$ grep -F 'Apple/One-plus/Samsung/Mi/^[a-zA-Z]([\w -]*[a-zA-Z])?$/_Nokia/' match.txt >file1.txt $ grep -F -v "Apple/One-plus/Samsung/Mi/^[a-zA-Z]([\w -]*[a-zA-Z])?$/_Nokia/" match.txt \ > match.txt.tmp && mv match.txt.tmp match 

Expected output

$ cat file1.txt Apple/One-plus/Samsung/Mi/Sony/_Nokia/ Apple/One-plus/Samsung/Mi/Lenovo/_Nokia/ $ cat match Apple/One-plus/Samsung/Mi/HTC/OPPO/ 

How to move a line from a file to the other file on the basis of pattern matching?

1
  • Thank you @Fólkvangr for your suggestion, I am new here so I am not aware of rules but apologies for confusing you here. I have updated my question Commented Sep 9, 2018 at 12:10

4 Answers 4

1

Original issue

A regular expression cannot be specified with the -F option concerning grep. There is another issue concerning the regular expression. If the character ^ is used as an anchor to match the beginning of a line, then, it must be the first character of the regular expression.

prompt% cp -v input input.back prompt% grep -e "$regex" input.back > output prompt% grep -v "$regex" input.back > input 

Regular expression: the original poster did not provide a concrete input, therefore, it is difficult to find a suitable regular expression.

Edit: finally, the original poster has provided a sample input file.

Apple/One-plus/Samsung/Mi/Sony/_Nokia/ Apple/One-plus/Samsung/Mi/Lenovo/_Nokia/ Apple/One-plus/Samsung/Mi/HTC/OPPO/ 

Regular expression: regex

regex='\([-[:alpha:]]\+\/\)\{5\}_Nokia\/' 

Alternative solutions

These similar solutions are not recommended for beginners whom have never read the sed manual.

sed -n "/$regex/p;/$regex/d;w input" input.back > output 

Roughly speaking, the lines matching the regular expression are saved in the file output, then, they are deleted from the corresponding sed buffer and the buffer content is written in the file input.

sed -i.back -e "/$regex/w output" -e "/$regex/d" input 

These commands have subtle differences but the second one is more convenient.

0

If you have a suitably recent version of GNU awk (gawk) you could do

awk -i inplace -F'/' '$7 == "_f" {print > "otherfile"; next} 1' file 

If your awk doesn't support the -i inplace option, then you can do the same thing but redirect the output to a temporary file and then rename it.

2
  • what's the point of the next there? it's not a useless usage for single block? Commented Sep 7, 2018 at 4:27
  • @αғsнιη the next is what turns it from a copy to a move (i.e. it prints to otherfile, but skips the default print to the original file) Commented Sep 7, 2018 at 11:05
0

How about this proposition? This is a less concise proposition than @steeldriver's answer, nonetheless, it is a progressive solution (step by step).

$ cut -d/ -f7 data.txt | grep -n _f | cut -d: -f 1 | xargs -i sed -n {}p data.txt > otherfile.txt 
  • _f is the pattern when matched is created to the other file.

  • data.txt is your file

  • / is your delimiter

If this worked, then do a comm to work out what should remain in the original file.

$ comm -23 data.txt otherfile.txt > remainder.txt 

remainder.txt is your data.txt with the bits removed.

5
  • Thanks @Rui first part is working fine as per the requirement but second command $ comm -1 data.txt otherfile.txt > remainder.txt is not working as per the requirement basically it is only creating new file with out moving data from original file. Commented Sep 9, 2018 at 12:14
  • Doesnt remainder.txt have the contents of what you want? If so, then rename remainder.txt to be data.txt and you have your solution, no? Commented Sep 9, 2018 at 22:39
  • no, remainder.txt is containing the same data as otherfile.txt. I have tried comm -23 otherfile.txt data.txt but no luck. Commented Sep 10, 2018 at 7:43
  • My mistake... comm -23 is what you want. I have edited the answer. Order of the files makes a difference. Commented Sep 10, 2018 at 9:25
  • As in comm -23 otherfile.txt data.txt will not give you what you want BUT comm -23 data.txt otherfile.txt will give you what you want. Commented Sep 11, 2018 at 5:57
0

You can first move the intended lines to the other file (outemp.txt) by:

sed -n '/_/w outemp.txt' input_file 

then remove those lines from your input_file by:

sed -i '/_/d' input_file 

check the result:

cat outemp.txt Apple/One-plus/Samsung/Mi/Sony/_Nokia/ Apple/One-plus/Samsung/Mi/Lenovo/_Nokia/ cat input_file Apple/One-plus/Samsung/Mi/HTC/OPPO/ 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.