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
    A regular expression can not be specified with the -F option (--fixed-strings). For more information, look at the man page (man grep) or read the Grep manual (info grep). – Fólkvangr Sep 7 '18 at 5:44
  • Your issue would be more noticeable with concrete examples (vs abstract descriptions). Could you provide some concrete examples? – Fólkvangr Sep 7 '18 at 5:54
  • You may comment or ask questions below your post. Remember to validate the answer that satisfies you by clicking on the colored checkmark next to the answer. – Fólkvangr Sep 8 '18 at 10:09
  • 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 – sam Sep 9 '18 at 12:10
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.

  • what's the point of the next there? it's not a useless usage for single block? – αғsнιη Sep 7 '18 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) – steeldriver Sep 7 '18 at 11:05
0

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

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.

  • 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. – sam Sep 9 '18 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? – chai Sep 9 '18 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. – sam Sep 10 '18 at 7:43
  • My mistake... comm -23 is what you want. I have edited the answer. Order of the files makes a difference. – chai Sep 10 '18 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. – chai Sep 11 '18 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.