我想OK
从目录中递归输出包含该单词的所有行。但我需要从结果中排除一些扩展:
*~
*.map
*.js except *.debug.js
我试过:
grep -r --exclude={*~,*.map} "OK" /some/dir
除了我不知道如何从结果中删除所有这些非调试.js
文件。
答案1
我只想通过一秒钟来grep
删除它们:
grep -r --exclude={\*~,\*.map} "OK" bar/ | grep -vP '(?<!debug)\.js'
反转-v
匹配,打印与模式不匹配的行,并-P
启用 Perl 兼容正则表达式,让我们可以使用消极的回顾。这个特定的正则表达式将.js
匹配不是前面的debug
这意味着(因为我们正在反转匹配)只有那些.js
文件才会被打印。
然而,正如 @QuestionOverflow 在评论中指出的那样,这可能会产生过滤掉的意想不到的副作用线包含OK
和js
因为grep -v
应用于整个输出,而不仅仅是文件名。为了避免这种情况,只需添加一个冒号(这是grep
用来分隔文件名和文件内容的):
grep -r --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js:'
如果您的输入行包含foo.js:
或文件名包含:
.因此,可以肯定的是,使用不同的方法:
grep -Tr --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js\t'
导致在文件名和文件内容之间打印制表符-T
。grep
因此,如果我们只是将 a 添加\t
到正则表达式的末尾,它将仅匹配文件名,而不匹配该行的内容。
仍然,使用find
无论如何都可能更有意义。
答案2
我用来find
定位文件并通过管道传输结果xargs
:
$ find . -type f \! -name "*~" \
\! -name "*.map" \
\! \( -name "*.js" -and \! -name "*.debug.js" \) \
-print0 | xargs -0 grep "OK"
这会搜索每个文件不是匹配“ *~
”、“ *.map
”或“*.js
但不匹配*.debug.js
”。
使用find
您可以轻松搜索相当复杂的规则,这种方法可以避免您意外删除 double 可能发生的误报grep
。
答案3
和zsh
你一起可以做到:
setopt extendedglob
grep OK some/dir/**/^(*~|*.map|(^*debug).js)
当然,前提是参数列表不太长,在这种情况下你总是可以这样做:
printf '%s\0' some/dir/**/^(*~|*.map|(^*debug).js) | xargs -0 grep OK
答案4
如果您不介意看到输出稍微乱序(如果您这样做,您可以对其进行排序):
grep -r --exclude={*~,*.map,*.js} "OK" /some/dir **/*.debug.js
这要求您的 shell 支持**
递归通配符:zsh 是开箱即用的,bash 在您运行后执行shopt -s globstar
,ksh93 在您运行后执行set -o globstar
。
如果没有**
shell 的支持,您可以使用两个 grep 命令:
grep -r --exclude={*~,*.map,*.js} "OK" /some/dir
grep -r --include=*.debug.js "OK" /some/dir