bash event not found trying to match and exclude parenthesis in grep
Solution 1
The rules are different for single quotes versus double quotes.
For the reason you show, double quotes can't be used reliably in bash, because there's no sane way to escape an exclamation mark.
$ grep -oP "\\(.*(?!word).*right"
bash: !word: event not found
$ grep -oP "\\(.*(?\!word).*right"
grep: unrecognized character after (? or (?-
The second is because bash passes through \!
rather than !
to grep. Showing this:
$ printf '%s' "\!"
\!
When you tried single quotes, the double backslash doesn't mean an escaped backslash, it means two backslashes.
$ printf '%s' '\\(.*(?!word).*right'
\\(.*(?!word).*right
Inside single quotes, everything is literal, and there are no escapes, so the way to write the regular expression you're trying is:
$ grep -oP '\(.*(?!word).*right'
Solution 2
If you want to match from the second open parentheses up until (but not including) the next closing parentheses:
grep -Po '\(.*?\K\([^)]*'
Or portably with sed
:
sed -n 's/^[^(]*([^(]*\(([^)]*\).*/\1/p'
To match the right most (
that is not followed by word
up to the rightmost right
after that:
grep -Po '.*\K\((?!word).*right'
Solution 3
You can do it with simple awk
:
$ echo '(foo),(bar,baz(word,right),(end)' | awk -F'),' '{print $2}'
(bar,baz(word,right
Related videos on Youtube
Philippe Blayo
One of the best experience in my life has been to enjoy pair programming with developers that value clean code and simple design. It's called eXtreme Programming and I hope one day I'll have the opportunity to do it again.
Updated on September 18, 2022Comments
-
Philippe Blayo over 1 year
In a very long line I'll summarize with:
(foo),(bar,baz(word,right),(end)
I want to print only:
(bar,baz(word,right
To match the second parenthesis, I exclude the word that follows the third one:
$ grep -oP "\\(.*(?!word).*right"
but Bash interprets the exclamation mark:
-bash: !word: event not found
Protecting the exclamation mark with single quote fails with
grep: missing )
$ grep -oP '\\(.*(?!word).*right' $ grep -oP '\\((?!word)(.*right)'
Protecting the exclamation mark with backslash fails with
grep: unrecognized character after (? or (?-
Any idea?
Note:
-P
is for Perl regex and-o
is to print only the matching part of a line-
Angel Todorov about 10 yearsuse
set +H
to turn off history expansion,set -H
to turn it back on. -
Gilles 'SO- stop being evil' about 10 years@glennjackman Or just use proper quoting: single quotes in this case. (Which gets to the next step that the regex isn't syntactically correct.)
-