【问题标题】:Multiple grep search/ignore patterns多个 grep 搜索/忽略模式
【发布时间】:2010-11-24 10:00:14
【问题描述】:

我通常使用以下管道对特定搜索字符串进行 grep,但忽略某些其他模式:

grep -Ri 64 src/install/ | grep -v \.svn | grep -v "file"| grep -v "2\.5" | grep -v "2\.6"

这可以用简洁的方式实现吗?我正在使用 GNU grep 2.5.3。

【问题讨论】:

  • 答案的有用性还取决于哪些字符串可能会更改。如果唯一变化的字符串是“64”,为什么不为此创建一个函数或 shell 脚本?

标签: unix shell command-line grep


【解决方案1】:

只需将未过滤的输出通过管道传输到 grep 的单个实例中,并使用扩展的正则表达式来声明您要忽略的内容:

grep -Ri 64 src/install/ | grep -v -E '(\.svn|file|2\.5|2\.6)'

编辑:要搜索多个文件,不妨试试

find ./src/install -type f -print |\
    grep -v -E '(\.svn|file|2\.5|2\.6)' | xargs grep -i 64

编辑:哦。我忘了添加一个简单的技巧来停止使用多个 grep 实例,即

ps -ef | grep something | grep -v grep

替换为

ps -ef | grep "[s]omething"

消除了第二个 grep 的需要。

【讨论】:

  • 括号必须用引号引起来.. 否则 bash 会报错:语法错误靠近意外标记 `('
  • 您的解决方案和我的问题中的示例中存在一个错误:第二个 grep 将匹配实际行 出现在第一个 grep 输出中的文件名。这有利于忽略 .svn .. 但不适用于其他模式。
  • 嗯,不确定你在说什么,但也许可以试试上面的更新
  • 您可能希望颠倒删除文件名的grep -vxargs 的顺序,以便xargs 只获取您想要开始grep 的文件。
  • 如果 grep -v .svn 是为了阻止 SVN 文件中的匹配项,那么 find src/install -type f -name '*.svn' -o -print | xargs fgrep 64 | egrep -lv 'file|2\.[56]' 怎么样
【解决方案2】:

使用-e 选项指定多个模式:

grep -Ri 64 src/install/ | grep -v -e '\.svn' -e file -e '2\.5' -e '2\.6'

您可能还对-F 标志感兴趣,它表示模式是固定字符串而不是正则表达式。现在您不必转义点:

grep -Ri 64 src/install/ | grep -vF -e .svn -e file -e 2.5 -e 2.6

我注意到你正在寻找“.svn”。您可能希望在初始递归 grep 中跳过任何名为“.svn”的目录。如果我是你,我会这样做:

grep -Ri 64 src/install/ --exclude-dir .svn | grep -vF -e file -e 2.5 -e 2.6

【讨论】:

    【解决方案3】:

    你可以用 awk 代替 grep

    awk '/64/&&!/(\.svn|file|2\.[56])/' file
    

    【讨论】:

    • 这简洁地从单个文件打印行,但无法从第一个 grep 进行递归。但它可以与建议的find | xargs 解决方案结合使用。不过,还应该在匹配之前添加文件名的打印,以便完全模拟 grep 行为。
    【解决方案4】:

    您可能想要使用ack-grep,它也允许使用 perl 正则表达式排除并避免所有 VC 目录,非常适合 grepping 源代码。

    【讨论】:

    • 感谢指点;对于纯 Python 源代码树,我目前使用来自 pylib.orgpy.lookup
    【解决方案5】:

    以下脚本将删除除文件列表之外的所有文件:

    echo cleanup_all $@
    
    
    if [[ $# -eq 0 ]]; then
    FILES=`find . -type f`
    else
    EXCLUDE_FILES_EXP="("
    for EXCLUDED_FILE in $@
    do
        EXCLUDE_FILES_EXP="$EXCLUDE_FILES_EXP./$EXCLUDED_FILE|"
    done
    # strip last char
    EXCLUDE_FILES_EXP="${EXCLUDE_FILES_EXP%?}"
    EXCLUDE_FILES_EXP="$EXCLUDE_FILES_EXP)"
    echo exluded files expression :  $EXCLUDE_FILES_EXP
    
         FILES=`find . -type f | egrep -v $EXCLUDE_FILES_EXP`
    fi
    
    echo removing $FILES
    
    for FILE in $FILES
    do
        echo "cleanup: removing file $FILE"
        rm $FILE
    done   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 2020-01-21
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      • 2021-03-14
      相关资源
      最近更新 更多