bash Shell UNIX:grep 通配符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21492833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shell UNIX : grep wild card
提问by Arthur Sigma
I can't figure out why the wild character * is interpreted differently in the following examples with grep :
我无法弄清楚为什么在以下带有 grep 的示例中对通配符 * 的解释不同:
find . -type f -name \*
Results :
结果 :
./tgt/etc/test_file.c
./tgt/etc/speleo/test_file.c
./tgt/etc/other_file.c
./src/file.c
I want to return from this command the files that match a pattern with eventually a wildcard *. But :
我想从这个命令返回匹配模式的文件,最终是一个通配符 *。但 :
find . -type f -name \* | grep "tgt/etc/*" # this one works
find . -type f -name \* | grep tgt/etc/* # not this one
find . -type f -name \* | grep tgt/et*/s* # this one works
find . -type f -name \* | grep "tgt/et*/s*" # not this one
I'd like to have an implementation which works fine with both cases. What should I use ?
我想要一个在这两种情况下都能正常工作的实现。我应该用什么?
回答by Barmar
The first argument to grep
is not a wildcard, it's a regular expression. In a regular expression, *
means to match any number of the character or expression that precedes it. So
的第一个参数grep
不是通配符,它是一个正则表达式。在正则表达式中,*
表示匹配任意数量的字符或前面的表达式。所以
grep "tgt/etc/*"
means to match tgt/etc
followed by zero or more /
characters. In a wildcard, *
means to match any number of any characters, the equivalent regular expression is .*
. For your purposes, the commands you want are:
表示匹配tgt/etc
后跟零个或多个/
字符。在通配符中,*
表示匹配任意数量的任意字符,等效的正则表达式为.*
. 出于您的目的,您需要的命令是:
find . -type f -name \* | grep "tgt/etc/"
find . -type f -name \* | grep "tgt/et.*/s"
Also, if you don't quote the argument, and it contains any *
characters, the shell will expand the argument as a filename wildcard before passing them as arguments to grep
. So when you write:
此外,如果您不引用参数,并且它包含任何*
字符,shell 将在将参数作为参数传递给grep
. 所以当你写:
find . -type f -name \* | grep tgt/etc/*
the shell will expand this to
外壳会将其扩展为
find . -type f -name \* | grep tgt/etc/file1 tgt/etc/file2 tgt/etc/file3
This will treat the tgt/etc/file1
as the regular expression to search for, and look for it inside the remaining files -- it will notprocess the input from the pipeline because it was given filename arguments.
这会将 视为tgt/etc/file1
要搜索的正则表达式,并在其余文件中查找它——它不会处理来自管道的输入,因为它被赋予了文件名参数。
回答by Christopher Creutzig
The unquoted examples (without the "
) are expanded by the shell, before grep
ever sees them. That is just the way Unix shells work.
未引用的示例(没有"
)在grep
看到它们之前由外壳展开。这就是 Unix shell 的工作方式。
For the quoted ones, note that *
in a grep pattern means something different from what it means to the shell and to find
: It means “repeat the preceding character any number of times (including zero).”
对于引用的那些,请注意*
在 grep 模式中的含义不同于它对 shell 和 to 的find
含义:它的意思是“重复前面的字符任意次数(包括零)”。
回答by zmo
it's because grep
uses regexps and no wildcards.
这是因为grep
使用正则表达式而没有通配符。
so basically, what you do is:
所以基本上,你要做的是:
tgt/etc/*
checking zero or sereval/
tgt/et*/s*
checking zero or severalt
and zero or severals
tgt/etc/*
检查零或sereval/
tgt/et*/s*
检查零个或多个t
和零个或多个s
but thing is that when you do not put quotes around the regexp, the shell is expanding the *
as wildcards, which messes up the regexp grep sees.
但问题是,当您不在正则表达式周围加上引号时,shell 会将*
通配符扩展为通配符,这会弄乱 grep 看到的正则表达式。