-P, --perl-regexp
Interpret I<PATTERNS> as Perl-compatible regular
expressions (PCREs). This option is experimental when
combined with the -z (--null-data) option, and grep -P
may warn of unimplemented features.
As everything (python, Go, javascript, etc, etc) uses perl regexps now-a-days and I can never remember which things I need to escape for old gods regexp.grep -Po "Name:\K\w+"
Lets assume we have a log file with a bunch of relevant stuff, I want to highlight my search term, BUT I also want to keep all the other lines around for context:
$ dmesg
...SNIP...
[2334597.539661] sd 1:0:0:0: [sdb] Attached SCSI removable disk
[2334597.548919] sd 1:0:0:0: [sdb] 57280429 512-byte logical blocks: (29.3 GB/27.3 GiB)
[2334597.761895] sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[2334597.761900] sdb: detected capacity change from 0 to 57280429
[2334597.772736] sdb:
[2334631.115664] sdb: detected capacity change from 57280429 to 0
...SNIP...
A simple grep, will only return the selected lines: $ dmesg | grep capacity
[2334597.761900] sdb: detected capacity change from 0 to 57280429
[2334631.115664] sdb: detected capacity change from 57280429 to 0
But I want all lines: $ dmesg | grep --color -e capacity -e ''
...SNIP...
[2334597.539661] sd 1:0:0:0: [sdb] Attached SCSI removable disk
[2334597.548919] sd 1:0:0:0: [sdb] 57280429 512-byte logical blocks: (29.3 GB/27.3 GiB)
[2334597.761895] sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
*[2334597.761900] sdb: detected capacity change from 0 to 57280429*
[2334597.772736] sdb:
*[2334631.115664] sdb: detected capacity change from 57280429 to 0*
...SNIP...
The null trick also works well on directories with many small files, like /proc/ or /sys/. Say, for example, you wanted to get the filename and value of each file: $ grep -R '' /sys/module/iwlwifi/parameters/
/sys/module/iwlwifi/parameters/nvm_file:(null)
/sys/module/iwlwifi/parameters/debug:0
/sys/module/iwlwifi/parameters/swcrypto:0
/sys/module/iwlwifi/parameters/power_save:N
/sys/module/iwlwifi/parameters/lar_disable:N
...SNIP... grep --color "$1"'\|$'I use ripgrep when I need better speed. I've pretty much switched to ripgrep these days, but still use GNU grep when I'm answering questions on stackoverflow, reddit, etc.
>ABC flags
Good to also know about `--group-separator` and `--no-group-separator` when there are multiple non-contiguous matches. Helps to customize the separator or remove them altogether. Sadly, these options are still not explained in `man grep` on Ubuntu. You'll have to use `info grep` or the online manual to find them.
Options I use often that is not mentioned in the article:
* `-c` to count the number of matches
* `-F` for fixed string matching
* `-x` to match whole lines
* `-P` for PCRE (as mentioned in many comments here)
* `--color=auto` this is part of command name alias, so it is always used
I wrote a book as well on "GNU grep and ripgrep": https://github.com/learnbyexample/learn_gnugrep_ripgrep Free to read online.
function fvi { grep -rl $1 . | xargs nvim +/$1 }
It greps a directory recursively and opens files which have a pattern and puts the pattern in the search buffer. #!/bin/sh
usage () {
cat >&2 <<'__USAGE__'
usage: git gsr [-P | --perl-regexp] <old> <new> [paths...]
replace all occurrances of <old> with <new> optionally limited to
<paths...> (as interpreted by git grep)
-P, --perl-regexp interpret <old> as perl regular expression;
default is to treat it as a fixed string.
__USAGE__
exit 1
}
pattern='-F'
perl='BEGIN {($old, $new) = (shift, shift)} s/\Q$old\E/$new/g'
case "$1" in
-P|--perl-regexp)
shift
pattern='-P'
perl='BEGIN {($old, $new) = (shift, shift)} s/$old/$new/g'
;;
-*) usage
;;
esac
test $# -lt 2 && usage
old=$1; new=$2; shift; shift
git grep -l -z $pattern "$old" -- "$@" |
xargs -0 perl -pi -e "$perl" "$old" "$new" sed -n 's/.*\(pattern\).*/\1/p'
it can instead simply be: grep -o 'pattern'
The -w flag is new to me today - excited to save still more keystrokes![0] - https://github.com/BurntSushi/ripgrep#why-should-i-use-ripgr...
LC_ALL=C grep -larP '\x1A\x2B\x3C\xFF' grep -larF "$(printf '\032\053\074\377')"
The -F flag should also make this faster as it doesn't actually need to use a regular expression engine, let alone a Perl-compatible one.Caveats:
1) POSIX only requires printf to recognize octal escapes (\nnn, or \0nnn if using %b specifier), not hexadecimal escapes. Many implementations recognize the latter, but not Debian dash.
2) Shell command substitution strips trailing new lines from the output, so if your binary string ends in a newline you'll need to use extra tricks. E.g. S="$(printf '\032\053\074\nX')"; grep -larF "${S%X}"
3) It's probably a good idea to still specify LC_ALL=C, but because the binary string is now being passed through the shell's innards it might need to be set in the environment of the shell itself, not simply the environments of the printf and grep subcommands. (Also, technically I'm not sure if the C/POSIX locale is required to be 8-bit clean, yet, but in practice it will be.)
Bash and some other shells support an extension ($') for expanding escape sequences inline:
grep -larF $'\x1A\x2B\x3C\xFF'
If you do any amount of shell programming--even if you only stick with Bash--it's worth spending 30 minutes reading the "Shell Command Language" chapter of the POSIX specification: https://pubs.opengroup.org/onlinepubs/9699919799/ The first few sections are the most concise resource available for explaining, step-by-step, shell parsing rules. find . -type f -name \*txt \; | xargs -I{} -P24 bash -c "grep -Hi foo '{}' ; :"(joking)
grep "foo.*bar" hello
Unfortunately, the basic grep syntax doesn't give you an easy way of specifying both orders, so that would have to be something like: grep -e "foo.*bar" -e "bar.*foo" hello
You can specify random order in a couple of different ways with Perl-compatible regexes, such as lookaheading the search terms from the end of line marker. But it's not as easy to read as it should be. cat hello | sed -n '/foo/{ /bar/{ /baz/ p }}' grep -nRI foo ./
Sometimes I add `-i`Often I will add `-P` and encase the regex with single-quotes of course
I also like --include and --exclude, especially since it allows regex for which files to look at
Living without those few "extensions" feels... empty
-l/-h/-v/-o show up every now and then