Issue
I want to grep through a file of files, with path, for arbitrary patterns (given at runtime)
The problem is that I do NOT want to match those arbitrary patterns if they're in the "library path" portion of the line. But not all lines start with the library path.
I.E. given a file:
/other/more.mp3
/home/more/Music/more.mp3
/home/more/Music/Music.mp3
/home/more/Music/something other.mp3
/home/more/Music/other/something.mp3
and a "library" path of "/home/more/Music"
The pattern "Music" should match only line 3. The pattern "more" should match lines 1 and 2, but not 3. The pattern "other" should match lines 1,4, and 5.
Things I've tried:
^\($LIBRARY\)\+.*$PATTERN
^\($LIBRARY\).*$PATTERN
I could pre-process the file to remove $LIBRARY and re-add it after, probably by finding the matching line in the original file. But that seems a bit excessive, surely there's a simpler way?
Solution
awk
is more suited for this job than grep
.
awk -v pat='more' -v lib='/home/more/Music' '{
s = $0; sub("^" lib, "", s)} s ~ pat' file
/other/more.mp3
/home/more/Music/more.mp3
# or else
awk -v pat='other' -v lib='/home/more/Music' '{
s = $0; sub("^" lib, "", s)} s ~ pat' file
/other/more.mp3
/home/more/Music/something other.mp3
/home/more/Music/other/something.mp3
# or else
awk -v pat='Music' -v lib='/home/more/Music' '{
s = $0; sub("^" lib, "", s)} s ~ pat' file
/home/more/Music/Music.mp3
Alternative gnu grep
solution:
lib='/home/more/Music'
# test 1
grep -ioP "^(?>$lib|).*more" file
/other/more
/home/more/Music/more
# test 2
grep -ioP "^(?>$lib|).*other" file
/other
/home/more/Music/something other
/home/more/Music/other
# test 3
grep -ioP "^(?>$lib|).*Music" file
/home/more/Music/Music
Note the use of atomic group in this regex, which is required to make sure we always match $lib
at the start when it is there.
Answered By - anubhava Answer Checked By - Mary Flores (WPSolving Volunteer)