【问题标题】:Is it possible to do a grep with keywords stored in the array?是否可以使用存储在数组中的关键字进行 grep?
【发布时间】:2010-02-19 09:57:29
【问题描述】:

是否可以对存储在数组中的关键字进行 grep。

这里是可能的代码sn-p;我该如何纠正?

args=("key1" "key2" "key3")

cat file_name |while read line
 echo $line | grep -q -w ${args[c]}
done

目前,我只能搜索一个关键字。我想搜索存储在 args 数组中的所有关键字。

【问题讨论】:

  • 虽然不是真正的解决方案,但是 cat 用于连接文件,如果只有一个文件,请使用输入指令: while read line echo $line | grep -q -w ${args[c]} 完成 en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat
  • 非常感谢..我习惯于通过查看其他示例来做到这一点..没有意识到..非常感谢

标签: bash shell grep


【解决方案1】:

您可以使用一些 bash 扩展魔术来为每个元素添加前缀 -e 并将数组的每个元素作为单独的模式传递。这可以避免一些优先级问题,您的模式可能会与 |运营商:

$ grep ${args[@]/#/-e } file_name

这样做的缺点是您的模式中不能有任何空格,因为这会将参数拆分为 grep。您不能在上述展开式周围加上引号,否则您会得到“-e 模式”作为 grep 的单个参数。

【讨论】:

    【解决方案2】:

    我倾向于对所有内容都使用进程替换。与grep-f 选项结合使用很方便:

    从 FILE 中获取模式,每行一个。

    (根据具体情况,您甚至可能希望将其与 -x-w 结合使用以获得出色的效果。)

    所以:

    #! /usr/bin/env bash
    
    t=(8 12 24)
    
    seq 30 | grep -f <(printf '%s\n' "${t[@]}")
    

    我得到:

    8
    12
    18
    24
    28
    

    我基本上写了一个伪文件,每行包含一个数组项,然后告诉grep 使用这些行中的每一行作为模式。

    【讨论】:

      【解决方案3】:
      args=("key1" "key2" "key3")
      pat=$(echo ${args[@]}|tr " " "|")
      grep -Eow "$pat" file
      

      或者带壳

      args=("key1" "key2" "key3")
      while read -r line
      do
          for i in ${args[@]}
          do
              case "$line" in
                  *"$i"*) echo "found: $line";;
              esac
          done
      done <"file"
      

      【讨论】:

        【解决方案4】:

        这是一种方式:

        args=("key1" "key2" "key3")
        keys=${args[@]/%/\\|}      # result: key1\| key2\| key3\|
        keys=${keys// }            # result: key1\|key2\|key3\|
        grep "${keys}" file_name 
        

        编辑:

        基于 Pavel Shved 的建议:

        ( IFS="|"; keys="${args[*]}"; keys="${keys//|/\\|}"; grep "${keys}" file_name )
        

        作为单线的第一个版本:

        keys=${args[@]/%/\\|}; keys=${keys// }; grep "${keys}" file_name
        

        编辑2:

        比使用IFS的版本还要好:

        printf -v keys "%s\\|" "${args[@]}"; grep "${keys}" file_name
        

        【讨论】:

        • 您能解释一下您的解决方案是如何工作的吗?我一直在理解 % 在您的模式 args[@]/%/\\| 中的目的
        • @Sharad:查看]Bash Manual at Shell Parameter Expansion](gnu.org/software/bash/manual/…) 在最后一段的旁边。我的示例中的赋值keys=${args[@]/%/\\|} 表示将数组 (args[@]) 的每个元素的结尾 (/) 替换为 (/) 反斜杠和管道 (\\|) .所以它添加了这些字符,因为“结束”(% 后跟没有其他字符匹配)就是这样 - 在这种情况下,在“替换”期间没有删除任何字符。
        【解决方案5】:

        命令

        ( IFS="|" ; grep --perl-regexp "${args[*]}" ) <file_name
        

        在文件中搜索数组中的每个关键字。它通过构造正则表达式 word1|word2|word3 来匹配给定选项中的任何单词(在 perl 模式下)。

        如果我有办法将数组元素连接成一个字符串,用 sequence 个字符(即\|)分隔它们,那么它可以在没有 perl 正则表达式的情况下完成。

        【讨论】:

        • 在我的系统上,它是单数:--perl-regexp。此外,cat 的无用使用。
        • ( IFS ... grep ... file_name ) - 无需重定向。你的grep--perl-regexp 中真的有“s”吗?
        • @Dennis,不,它没有“s”,我粘贴的版本有错字。
        【解决方案6】:

        也许是这样的;

        cat file_name |while read line
        for arg in ${args[@]}
        do
        echo $line | grep -q -w $arg}
        done
        done
        

        未测试!

        【讨论】:

        • 好吧,我需要同时搜索这两个关键字,例如 ${args[*]} 或 egrep 与多个关键字。有什么想法吗?
        猜你喜欢
        • 2019-10-28
        • 2018-10-17
        • 2014-04-30
        • 1970-01-01
        • 2018-07-19
        • 2017-02-01
        • 1970-01-01
        • 2013-10-23
        • 1970-01-01
        相关资源
        最近更新 更多