我的 grep 版本是grep (BSD grep) 2.5.1-FreeBSD
,我的操作系统是OSX 10.13.3 (17D47)
我有一个 gitbook 存储库,并且有一个名为_book
我想在使用 grep 时忽略的临时目录。
当我使用 时grep -Fnrl mysql ./ --exclude-dir={_book}
,它没有排除该_book
目录。结果看起来像
...
.//UTILITIES/my_utils/shell_scripts/get_several_days_mysql_data_log.sh
.//_book/search_jieba_index.dat
.//_book/LANGUAGES/awk/awk_magic.html
但该命令grep -Fnrl mysql ./ --exclude-dir "_book"
给了我我所期望的结果,结果看起来像
...
.//UTILITIES/my_utils/shell_scripts/get_several_days_mysql_data_log.sh
我在 stackoverflow 上搜索过,发现一个问题提到了第一个命令样式并获得了 3 个赞成票,所以我猜它在某些情况下有效。
问题链接是:使用带有 --exclude-dir 标志的 grep 来排除多个目录
为什么会发生这种情况?
如果我想使用第一种命令方式排除成功怎么办_book
?
答案1
那篇文章正在利用 bash 的大括号扩展:
$ printf "%s\n" --exclude-dir={a,b,c}
--exclude-dir=a
--exclude-dir=b
--exclude-dir=c
但是,当只有一个元素时,不会应用大括号扩展,并且大括号保持原样:
$ printf "%s\n" --exclude-dir={a}
--exclude-dir={a}
由于大括号扩展是 bash(和其他一些 shell)的功能,而不是 grep 的功能,因此对于 grep 来说,它看起来像是您告诉它排除名为{_book}
.
答案2
这些并不是不同的“命令风格”。他们正在利用一个巴什特征,而不是grep
特征。
通过运行以下命令来阅读它:
LESS='+/Brace Expansion' man bash
当大括号内有逗号分隔的值时,您的壳grep
在看到它们之前将它们扩展到多个参数。
由于您只传递一个目录,因此不需要大括号扩展。
当您使用的大括号之间只有一个项目(没有逗号和双句点来指示范围)时,您的 shell 会单独保留大括号。您需要传递grep
文字名称{_book}
,这不是您想要排除的目录。
值得一提的是,您也不需要双引号。
grep -Fnrl mysql ./ --exclude-dir _book
...会工作得很好。
双引号不会造成任何损害,但也不是必需的。你可以用它们全部参数具有相同的结果,因为引号在 shellgrep
看到它们之前就被删除了。
grep '-Fnrl' "mysql" './' "--exclude-dir" \_\b\o\o\k
您甚至可以引用命令名称本身'grep'
,尽管它有一个轻微地不同的含义。具体来说,它抑制别名查找。例如,在 Ubuntu 系统上,grep
通常别名为grep --color=auto
.引用"grep"
(或其任何部分)将绕过此别名。
gr\ep -Fnrl mysql ./ --exclude-dir _book
这个故事的寓意是,了解您所使用的语言的引用规则。
或者您可能会“犯”错误并产生令人困惑的结果。