开发者

Question about shell commands and grep

开发者 https://www.devze.com 2023-03-04 10:29 出处:网络
Does anyone know why grep \"p\\{2\\}\" textfile will find \"apple\" if it\'s in the file, but grep p\\{2\\} textfile

Does anyone know why

grep "p\{2\}" textfile

will find "apple" if it's in the file, but

grep p\{2\} textfile

won't?

I'm new to using a开发者_开发技巧 command line and regular expressions, and this is puzzling me.


Although this has already been answered, but since you are new to all this stuff, here is how to debug it:

-- get the pid of current shell (using ps).

 PID TTY          TIME CMD

 1611 pts/0    00:00:00 su

 1619 pts/0    00:00:00 bash

 1763 pts/0    00:00:00 ps

-- from some other shell, attach strace (system call tracer) to the required pid (here 1619):

strace -f -o <output_file> -p 1619

-- Run both the commands that you tried

-- open the output file and look for exec family calls for the required process, here: grep

The output on my machine is some thing like:

1723  execve("/bin/grep", ["grep", "--color=auto", "p{2}", "foo"], [/* 19 vars */]) = 0

1725  execve("/bin/grep", ["grep", "--color=auto", "p\\{2\\}", "foo"], [/* 19 vars */]) = 0

Now you can see the difference how grep was executed in both the cases and can figure out the problem yourself. :)

still the -e flag mystery is yet to be solved....


Without the quotes, the shell will try to expanding the options. In your case the curly brackets '{}' have a special meaning in the shell much like the asterisk '*' which expands to a wildcard.


With quotes, your complete regex gets passed directly to grep. Without the quotes, grep sees your regex as p{2}.

Edit:

To clarify, without the quotes your slashes are being removed by shell before your regex is passed to grep.

Try:

echo grep p\{2\} test.txt

And you'll see your output as...

grep p{2} test.txt

The quotes prevent shell from escaping characters before they get to grep. You could also escape your slashes and it will work without quotes - grep p\\{2\\} test.txt


The first one greps the pattern using regex, then pp:

echo "apple" | grep 'p\{2\}'

The second one greps the pattern literally, then p{2}:

echo "ap{2}le" | grep p\{2\}


From the grep man page

In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).

so these two become functional equivalent

egrep p{2} 

and

grep "p\{2\}" 

the first uses EREs(Extended Regular Expressions) the second uses BREs(Basic Regular Expressions) in your example because your using grep(which supports BREs when you don't use the -e switch) and you're enclosed in quotes so "\{" gets expanded as a special BRE character.

You second instance doesn't work because your just looking for the literal string 2{p} which doesn't exist in your file

you can demonstrate that grep is expanding your string as a BRE by trying:

grep "p\{2"

grep will complain

grep: Unmatched \{  
0

精彩评论

暂无评论...
验证码 换一张
取 消