对 grep 和 * 通配符感到困惑

An *_*rer 5 command-line grep find

我正在运行以下命令以查找与“flash_drive_data”无关的所有文件/目录:

find . -not -path './flash_drive_data*' | grep "./*flash*"
Run Code Online (Sandbox Code Playgroud)

我尝试过的一些事情让我感到困惑:

1. 当我运行上面的命令时,我得到了一些“部分”命中(即它们与*flash*模式不完全匹配。例如:

./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/cli.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/signals.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/templating.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/sessions.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/json
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/json/tag.pyi
Run Code Online (Sandbox Code Playgroud)

所述3/flas在端部被突出显示。

2.当我grep "*flash*"用 just替换时grep "*",我希望找到 find 返回的所有文件,但我没有。为什么?然后,当我这样做时,grep "**"我相信我得到了所有文件(或者至少我认为我得到了)。再说一遍,这是为什么?

3. 最后,我上面所做的目的是确保当我运行时find . -not -path './flash_drive_data*'我没有得到任何与 flash_drive_data 相关的信息。似乎我做到了(正如我上面解释的那样,grep 有一些意想不到的行为)。但是,当我运行时: find . -not -path './flash_drive_data*' -exec tar cfv home.tar.bz '{}' +

我得到的输出包括:

./flash_drive_data/index2/ask-sdk-core/dist/dispatcher/error/handler/
Run Code Online (Sandbox Code Playgroud)

所以 flash_drive_data 文件被包括在内。

pLu*_*umo 15

您混淆了*for Shell Filename ExpansionPosix Basic Regex的不同含义。

在正则表达式中,*是它前面字符的量词,因此h*表示 0 次或多次出现h。如果您想要“任意数量的任意字符”,请使用.*.

grep '*'会寻找文字,*因为它前面没有任何东西可以量化,而grep '**'想要 0 次或多次出现*,所以一切都会适合,因为 0 次出现的东西总是适合。


不管怎么说,你应该喜欢使用find带有参数-path "*/flash/*",而不是grep输出find


ilk*_*chu 3

find . -not -path './flash_drive_data*' | grep "./*flash*"
Run Code Online (Sandbox Code Playgroud)

这里的事情是grep使用正则表达式,同时find -path使用 shell glob 样式模式匹配。星号在这两者中具有不同的含义。

正则表达式./*flash*首先匹配任意字符 ( .),然后匹配零个或多个斜杠 ( /*),然后是文字字符串flas,最后匹配任意数量(零个或多个)的h字符。3/flas匹配(零次h),例如reflash(零次/)。

您可以直接使用grep flash,因为它匹配输入中的任何位置,因此前导和尾随“匹配任何内容”部分是不必要的。

或者使用find -path './*flash*' -and -not -path './flash_drive_data*'

当我替换grep "*flash*"为 just时grep "*",我得到[没有匹配项]。

由于星号的意思是“任意数量的前一个原子”,因此这里并没有很好的定义。grep将其解释为字面星号,但实际上它应该是一个错误。

但是,当我运行:时,find . -not -path './flash_drive_data*' -exec tar cfv home.tar.bz '{}' +我得到的输出包括:

./flash_drive_data/index2/ask-sdk-core/dist/dispatcher/error/handler/

所以flash_drive_data文件被包含在内。

请注意,tar递归存储文件,并且第一个输出find.当前目录,因此所有内容都将被存储。您可能想要使用! -type dwithfind从输出中排除目录,或者(更好)-exclude=PATTERN查看tar.