okay so I wish to keep lines containing several keywords,
example of list:
Name:email:username #registered
Name2:email2:username2
Name3:email3:username3 #registered #subscribed #phonever
Name4:email4:username4 #unconfirmed
What I want to do is extract lines if they contain " #registered, #subscribed, #phonever
example of output I want,
Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever
With awk
(use regex alternation operator, |
, on a list of fixed strings):
awk '/#registered|#subscribed|#phonever/' file
The part under /.../
is called an awk
pattern and for the matching lines it executes the action that follows (as { ... }
). But since the default action is: { print $0 }
(printing the complete input record/line), there's no need to specify it here.
Similarly with sed
you could say:
sed -nE '/#registered|#subscribed|#phonever/p' file
but now we have to specify -n
to skip printing by default, and print with the p
command only those lines that match the pattern (called sed
address). The -E
tells sed
to used POSIX ERE (extended regex), and we need it here, because the default, POSIX BRE (basic regex) does not define the alternation operator.
For simple filtering (and printing the lines that match some pattern), grep
is also an option (and a very fast option at that):
grep '#registered\|#subscribed\|#phonever' file
awk
with patterns file)Solution for larger (and possibly dynamic) lists of patterns could be to keep all patterns in a separate file, for example in patterns
:
#registered
#subscribed
#phonever
and to use this awk
program:
awk 'NR==FNR { pat[$0]=1 } NR>FNR { for (p in pat) if ($0 ~ p) {print;next} }' patterns file
which will first load all patterns into pat
array, and then try to match any of those patterns on each of the lines in file
, printing and advancing on to the next line on the first match found.
The result is the same:
Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever
but the script now doesn't change for each new set of patterns. Note however, this caries a performance penalty (as general solutions usually do). For shorter lists of patterns and smaller files, this shouldn't be a problem.
grep
with fixed-string patterns file)Building on the approach from above (of keeping a list of fixed-string "patterns" in a file), we can actually use grep
-- which provides a specialized option (-f FILE
) for obtaining patterns from file, one per line. To further speed-up the matching, we should also use -F
/--fixed-strings
option.
So, this:
grep -Ff patterns file
will be incredibly fast, handling long lists of fixed-string patterns and huge files with minimal memory overhead.