1

When I do a search bindkey in the zsh plugins directory for key conflicts I get responses from both the .zsh script files and .md files, and some of the zsh readme files use a double quote in the bindkey statement.

How would I do a search for bindkeys using both ' and " for quoting? For instance if search for usage of Ctrl-R the first command using double quotes for the matching string produces the README.md of zsh-navigation-tools and single quotes produces the bindkey command for both vi-mode and zsh-navigation-tools

grep -r -i 'bindkey "^r' ~/.oh-my-zsh/plugins

output:

zsh-navigation-tools/README.md:    bindkey "^R" znt-history-widget
grep -r -i "bindkey '^r" ~/.oh-my-zsh/plugins

output:

vi-mode/vi-mode.plugin.zsh:bindkey '^r' history-incremental-search-backward
zsh-navigation-tools/zsh-navigation-tools.plugin.zsh:bindkey '^R' znt-history-widget

How can I create the command that will output all 3?

Does grep have the option of specifying an alternate quoting character that will allow both ' and " as literals?

  • 2
    you can escape double quotes inside when using double quotes... like "bindkey ['\"]^r" – Sundeep Jun 20 '17 at 16:36
2

Of course, you need to escape the ^ character:

grep -r 'bindkey "\^r' dir

Then, you could use the "Extended Regex" Alternate character '|':

grep -E 'bindkey "\^r''|'"bindkey '\^r"  dir

Which could be reduced to:

grep -E 'bindkey ("|'"')"'\^r' dir [1]

Or, if using bash, ksh or zsh, use the $' quoting (both ' and " could be escaped):

grep -E $'bindkey (\"|\')\^r' dir

And, finally, realize that there are two r: r and R:

grep -rE $'bindkey (\"|\')\^(r|R)' dir

Or use i (but that will change other characters also):

grep -riE $'bindkey (\"|\')\^r' dir

Of course, this is also a perl regex (GNU grep):

grep -rP $'bindkey (\"|\')\^(r|R)' dir

[1]It may be difficult to understand the quoting.
But it is simply a concatenation of three quoted parts.
A string quoted with single quotes followed by an string quoted with double quotes followed by a third string quoted again with single quotes. The easiest way to see the efect is to echo it. The shell will remove one quoting level and the string that the command actually receives becomes clear:

$ echo grep -E 'bindkey ("|'   "')"   '\^r' dir
grep -E  bindkey ("|   ')   \^r dir

Maybe it would be easier to see with:

$ echo grep -E 'a'"b"'c' dir
grep -E abc dir

The same could be written in one pair of single quotes.
Remember that single quotes can not be included inside single quotes:

$ echo grep -E 'bindkey ("|'\'')\^r' dir
grep -E bindkey ("|')\^r dir

Or inside double quotes (a double quote could be escaped inside double quotes). With the added risk that some other characters ($, `, \, * and @) have an special meaning inside double quotes (not inside single quotes):

$ echo grep -E "bindkey (\"|')\^r" dir
grep -E bindkey ("|')\^r dir

An alternative is to use a character list […] with \' and \":

$ grep -E 'bindkey '[\"\']'\^r' dir

That is still a three part string, but the middle is not quoted (and no spaces):

'bindkey '    [\"\']     '\^r'
  • I find it hard to understand the third example grep -E 'bindkey ("|'"')"'\^r' dir. Does it mean that the alternate | character matches the " to its left and the ' before the closing bracket, or does it match the " and ' immediately surrounding it? Because it looks like the expression is quoted by botn " and 'with the 2nd and 3rd " holding the ') allowing it to be concatenated to 'bindkey ("|' and then continuing with '\^r'. It looks like the regexp is concatenated from 'bindkey ("|', "')" and '\^r', ie both ' and " are quotes rather than one or the other – vfclists Jun 21 '17 at 21:46
  • 1
    @vfclists Yes, it is complex. The main idea is that a double quote should be enclosed inside single quotes '' and a single quote ' should be enclosed inside double quotes "". The whole effect should be clear if you echo the whole command. I'll expand on the detail in my answer. – Arrow Jun 21 '17 at 22:40
3

With P (--perl-regexp) option and character class [...]:

grep -Pri 'bindkey [\047\042]\^r' ~/.oh-my-zsh/plugins

  • [\047\042] - matches either single quote \047 or double quote \042

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.