如何在特定行中使用#标签查找和搜索所有文件

时间:2017-05-25 06:45:00

标签: macos vim terminal ag fzf

我试图找到一种方法来扫描我的OSX系统上的文件夹,查找特定行(第一行的#标签)中包含特定文本字符串(#SomeTag")的所有文件。为了澄清,我在文件中寻找文本,而不是文件名。

我尝试了agfzf以及组合,但无法按照我想要的方式运作。

我想搜索fzf的文件,这些文件在特定行中有一些标签。 例如:

#TagOne #TagTwo searchpattern

这将仅在第一行中包含#TagOne #TagTwo的文件中搜索searchpattern。

更新 到目前为止,我提出了这个解决方案,它可以工作,但它远非最佳,但它完全符合我的要求。找到文件后,脚本需要1-3个参数,我可以在所有找到的文件的内容中进行全文模糊搜索。

 #!/bin/sh
if [ "$#" == 1 ]; then
    ag -Ril $1 ./Evernote | xargs ag --nobreak --nonumbers --noheading . | fzf
fi
if [ "$#" == 2 ]; then
    ag -Ril $1 ./Evernote | xargs ag -il $2 | xargs ag --nobreak --nonumbers --noheading . | fzf
fi
if [ "$#" == 3 ]; then
    ag -Ril $1 ./Evernote | xargs ag -il $2 | xargs ag -il $3 | xargs ag --nobreak --nonumbers --noheading . | fzf
fi

2 个答案:

答案 0 :(得分:3)

for file in `find [path] -type f`; do head -1 $file | grep [pattern] >> /dev/null && echo $file; done

将[path]替换为您要搜索的目录,将[pattern]替换为您要查找的内容,例如'#TagOne #TagTwo searchpattern'。

for file in ``; do ....; done位迭代graves中代码返回的每一行(反引号),将每一行分配到一个名为“file”的东西中。在坟墓内部,我们有find [path] -type f,它可以找到路径中的所有“普通”文件(不包括链接,目录等),并打印将每个文件发送到stdout(由我们的for循环使用。)

然后我们在每个文件上调用head -1,这些文件只提取每个文件的第一行,并通过它为您的模式greps。由于我们不关心grep的正常输出,因此我将其重定向到/ dev / null以防止打印。方便的是,grep的退出代码可以被视为true / false,具体取决于它是否位于任何位置。只有当grep匹配第一行中的某些内容时,&& echo $file才会利用此功能打印文件名。

<强>更新 为了支持多种模式,您可以链接上述解决方案,但最终会为您需要的每种模式打开每个文件。如果您要搜索多种模式,请尝试以下操作:

for file in `find . -type f`; do                                                                    
  FIRSTLINE=`head -1 $file`;                                                                      
  if [[ $FIRSTLINE == *pattern1* &&                                                                     
        $FIRSTLINE == *pattern2* &&                                                                     
        $FIRSTLINE == *pattern3* ]];
  then
      echo $file;
  fi;
done

这可以全部压缩到一行用作别名,但是我们在这里越过一条线,bash并不是那么好。设置了我们在一个不能被正则表达式限制的模式上匹配的要求,你最好不要诉诸python:

#!/usr/bin/env python
from os import walk
from os.path import join
import sys

directory = sys.argv[1]  # Use the first argument as the directory to search

for root, subdirs, files in walk(directory):
    for file in files:
        path = join(root, file)
        line = open(path).readline()
        if ('TagOne' in line and      # You could also get these on 
                'TagTwo' in line and  # the command-line...
                'TagThree' in line):
            print path

答案 1 :(得分:0)

我相信ctags可以满足您的要求。它是一个使浏览大型源代码项目变得容易的工具。它提供了您在现代IDE中可能会习惯的一些功能,例如从当前源文件跳转到其他文件中的功能和结构的定义的功能。由于ctags本质上是一个缓存的索引,因此您可以搜索任何字符串并在您的项目/目录中找到其所有引用。 Ctags设计为在Vim和Emacs内部运行。注意:fzf.vim插件具有标签搜索功能。

在您的特定情况下,您需要添加一个自定义标签。我认为ctag的regex选项就足够了:

--regex-<LANG>=/line_pattern/name_pattern/[flags]
       Define regular expression for locating tags in specific language.

例如,您可以递归地扫描所有文本文件中的#word并将这些结果保存在标记文件中。首先创建一个ctags选项文件:

# ctags definition file for searching for tags. 
--langdef=hashtext
--map-hashtext=+.txt
--regex-hashtext=/.*(#[a-zA-Z0-9]*)/\1/h,hashtag/I   #define your regex here
--fields=+ln

为示例起见,假设此选项文件称为hashtext.ctags。接下来,然后在目录中运行ctags,如下所示:

ctags -R --options=hashtext.ctags *

这将递归搜索正则表达式并在tags文件中创建索引。在vim中打开您希望通过标签浏览的文件,并使用:tag函数。

一旦所有这些机器就绪,您就可以使用fzf搜索并跳转到各种标签。有关详细信息和示例设置,请参见此处:fzf tags。或者,最好使用fzf vim插件,该插件具有TagBTag命令。