2

Question

How do I escape a regex (PCRE) to use in bash (with ag)?

Attempts

ag (?!.*rib)(?=.*dist)^(\w+)$ # -bash: !.*wib: event not found
ag "(?!.*rib)(?=.*dist)^(\w+)$" # -bash: !.*wib: event not found
ag '(?!.*rib)(?=.*dist)^(\w+)$' # This does not crash, but finds nothing
ag (\?!.\*rib)(\?=.\*dist)^(\\w+)$ # -bash: !.*wib: event not found

Edit: I was incorrect - the third one above finds nothing (but it does seem to be thinking hard)

I'm using osx

$ bash -version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.
Ashley Coolman
  • 11,095
  • 5
  • 59
  • 81
  • 2
    The third option should work fine `ag '(?!.*rib)(?=.*dist)^(\w+)$'`. The `!` is the history expansion character which needs to be quoted – Inian May 03 '19 at 11:30
  • Ah, Sorry. The third option does not crash, but it does not find anything at all – Ashley Coolman May 03 '19 at 11:43

2 Answers2

2

Aaah, these are the damn exclamation marks :-) This message "event not found" because of the unescaped ! exclamation mark. Try with some random string:

echo !asdjweuwioeuoiu 
# -bash: !asdjweuwioeuoiu: event not found

But if you escape with quotation marks, it should not be expanded and interpreted by bash:

echo '!fkj90eruge90ru0e9ger0g'
# !fkj90eruge90ru0e9ger0g

So, the third line of your suggestions should work:

ag '(?!.*rib)(?=.*dist)^(\w+)$'
Tomas
  • 57,621
  • 49
  • 238
  • 373
  • Ah, Sorry. The third option does not crash, but it does not find anything at all – Ashley Coolman May 03 '19 at 11:43
  • @AshleyCoolman that's a different issue then :) Perhaps you need to debug your regex, who knows. – Tomas May 03 '19 at 17:30
  • Ugh. It was a badly written question. The regex works, but...yeah i need to include an example. I feel like maybe im assuming a feature of the regex engine. Anyway ill fix the q when i get infront of a physical keyboard – Ashley Coolman May 03 '19 at 18:14
  • @AshleyCoolman please write a different question for it. This one was about the "event not found" problem and this one is actually solved. Create a new question for the other problem. – Tomas May 04 '19 at 09:43
  • quick historical reminder of the !: https://unix.stackexchange.com/questions/3747/understanding-the-exclamation-mark-in-bash -- consider disabling the "feature." – gregory Jun 01 '19 at 19:50
0

Let's assume you have a file, foo.txt with four lines of the following text:

distribute
distrib
distrubte
dist

Then using ag from bash, you'd employ your regex as follows:

$ ag "(?\!.*rib)(?=.*dist)" foo.txt
3:distrubte
4:dist

Line 3 and 4 would return as found matches. Note: I used double quotes, not single and ONLY escaped the exclamation mark -- as I didn't want it interpreted by bash, but used in the regex. If I wanted it used, I could do something like this:

$echo dist
dist
$ag "!$$" foo.txt 
4:dist

Now line four is matched. What happened here is the !$ of !$$ was expanded by the shell as the last argument to the previous command, i.e. dist. And, the final $ was left as a literal, making the expanded command ag "dist$", and this matches the fourth line in file.

For this reason, I actually prefer to use/struggle with double quotes since they afford one the ability to swap in variables, arguments, and shell capabilities into Ag's search string. YMMV.

gregory
  • 10,969
  • 2
  • 30
  • 42