仅在与 ack 匹配模式的文件中搜索

com*_*pie 54 ack

只能通过匹配特定“glob”模式的文件进行确认搜索(例如:在所有名为“bar*.c”的文件中搜索 foo)。命令

ack foo "bar*.c"
Run Code Online (Sandbox Code Playgroud)

仅适用于当前目录。

注意:我知道 find -exec 是可能的:

find . -name "bar*.c" -type f -exec ack foo {} + 
Run Code Online (Sandbox Code Playgroud)

但我想要一个小而简单的 ack 命令,因为 find 不会跳过版本控制目录。

slm*_*slm 32

搜索目录

根据手册页中显示的概要,我会说是的,它可以处理目录,但是查看开关,它不能仅查找基于模式的文件。为此,您必须入伍find。该命令ack确实包含该选项--files-from=FILE,因此可以从find.

概要

       ack [options] PATTERN [FILE...]
       ack -f [options] [DIRECTORY...]
Run Code Online (Sandbox Code Playgroud)

用法

   --files-from=FILE
       The list of files to be searched is specified in FILE.  The list of
       files are separated by newlines.  If FILE is "-", the list is
       loaded from standard input.
Run Code Online (Sandbox Code Playgroud)

有一个--ignore-file=选项可能会给你你想要的东西,但实际使用似乎有点痛苦。

   --ignore-file=FILTERTYPE:FILTERARGS
       Ignore files matching FILTERTYPE:FILTERARGS.  The filters are
       specified identically to file type filters as seen in "Defining
       your own types".
Run Code Online (Sandbox Code Playgroud)

搜索特定类型的文件

我能想到的唯一另一种方法ack是使用它的--type开关:

   --type=[no]TYPE
       Specify the types of files to include or exclude from a search.
       TYPE is a filetype, like perl or xml.  --type=perl can also be
       specified as --perl, and --type=noperl can be done as --noperl.

       If a file is of both type "foo" and "bar", specifying --foo and
       --nobar will exclude the file, because an exclusion takes
       precedence over an inclusion.
Run Code Online (Sandbox Code Playgroud)

要查看可用的类型:

$ ack --help-types | grep -E "perl|cpp"
Run Code Online (Sandbox Code Playgroud)

格式。例如, --type=perl 和 --perl 都可以工作。--[no]cpp .cpp .cc .cxx .m .hpp .hh .h .hxx --[no]objcpp .mm .h --[no]perl .pl .pm .pod .t .psgi; 第一行匹配 /^#!.*\bperl/ --[no]perltest .t

例子

根据文件名(*.pm、*.pl、*.t 和 *.pod)和 shebang 行查找所有 Perl 文件。

$ ack -f --type perl 
examples/iwatch/iwatch/iwatch
examples/nytprof_perl/bad.pl
Run Code Online (Sandbox Code Playgroud)

查找所有 C++ 文件:

$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h
Run Code Online (Sandbox Code Playgroud)

在 bar*.c 中搜索 foo

那么你怎么能完成你想要的呢?好吧,您可能必须使用以下方法find来执行此操作:

$ find adir -iname "bar*.c" | ack --files-from=- foo
adir/bar1.c
1:foo
2:foo

adir/dir1/bar1.c
1:foo
2:foo
Run Code Online (Sandbox Code Playgroud)

您还可以使用ack的功能来搜索与文件名中的给定模式匹配的文件(使用-g <pattern>),然后将此列表传递给ackusing-x--files-from=-..

使用-x

$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo
Run Code Online (Sandbox Code Playgroud)

使用-files-from=-

$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,我们都会使用此正则表达式匹配您想要的文件名:

\bbar.*.c$
Run Code Online (Sandbox Code Playgroud)

这匹配名称为bar.*c并且在.c使用行尾锚点之后结束的文件$。我们还希望确保名称具有使用\b. 对于包含边界字符(例如$bar.c或 )的文件,这将失败%bar.c

  • tldr; ```ack -g '\bbar.*.c$' | ack -x foo``` (3认同)

小智 14

如果知道文件类型就很容易了,ack 知道很多文件类型。因此,例如,如果您只想在 C 文件中搜索,那么您可以这样做:

ack --cc 'string'
Run Code Online (Sandbox Code Playgroud)

但如果它不是已知的扩展之一,则需要定义自己的类型。这应该有效:

ack --type-set barc:match:/bar.+\.c/ --barc 'string'
Run Code Online (Sandbox Code Playgroud)

请注意,您需要 --type-set 和 --barc。

(感谢 Andy,他也在邮件列表中帮助解决了这个问题。)


com*_*pie 7

“ack 2 有什么新东西?” http://beyondgrep.com/ack-2.0/

使用 ack 2.0,您可以使用新的 -x 将文件名从一个 ack 调用传递到另一个调用。

ack2 -g -i filepattern | ack2 -x -w searchpattern
Run Code Online (Sandbox Code Playgroud)

只有我无法让它工作:

% ack -g "*bar*.c"
Invalid regex '*bar*.c':
Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE bar*.c/ at ack line 314.
Run Code Online (Sandbox Code Playgroud)

因此似乎 -g 需要一个正则表达式,而我想要一个“glob”风格的选项......

  • 是的,`-g` 需要一个正则表达式,而不是一个 glob。你可以把你的正则表达式写成`.*bar.*\.c$`。 (2认同)
  • @AndyLester 感谢您的确认。您喜欢 ack 的“glob”选项的想法吗? (2认同)

小智 7

这似乎是最快和最安全的:

find . -name '*.c' | ack -x 'some string'
Run Code Online (Sandbox Code Playgroud)

-x 从 STDIN 读取要搜索的文件列表。

但是,如果该文件可能在您的locate数据库中,这会更快:

locate --basename '*.c' | ack -x 'some thing'
Run Code Online (Sandbox Code Playgroud)

Locate 也可以接受老式的正则表达式,有点痛苦,但如果你正在寻找c文件,它可能是必需的。 例如

locate --basename --regexp '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    ack -x 'some thing'
Run Code Online (Sandbox Code Playgroud)

这只是转换为:“搜索所有以 c、cpp、h、hpp 或 cc 结尾的文件名。”