【问题标题】:Using a variable to pass grep pattern in bash使用变量在 bash 中传递 grep 模式
【发布时间】:2013-01-03 01:44:20
【问题描述】:

我正在努力传递变量中包含的几个 grep 模式。这是我的代码:

#!/bin/bash
GREP="$(which grep)"
GREP_MY_OPTIONS="-c"
for i in {-2..2}
do
  GREP_MY_OPTIONS+=" -e "$(date --date="$i day" +'%Y-%m-%d')
done
echo $GREP_MY_OPTIONS

IFS=$'\n'
MYARRAY=( $(${GREP} ${GREP_MY_OPTIONS} "/home/user/this path has spaces in it/"*"/abc.xyz" | ${GREP} -v :0$ ) )

这就是我想要它做的事情:

  • 确定/定义 grep 的位置
  • 分配一个变量 (GREP_MY_OPTIONS) 保存我将传递给 grep 的参数
  • 将多个模式分配给 GREP_MY_OPTIONS
  • 使用 grep 和我存储在 $GREP_MY_OPTIONS 中的模式搜索包含空格的路径中的多个文件并将它们保存在一个数组中

当我使用“echo $GREP_MY_OPTIONS”时,它正在生成我所期望的,但是当我运行脚本时它失败并出现以下错误:

/bin/grep: 无效选项 -- ' '

我做错了什么?如果路径中没有空格,一切似乎都可以正常工作,所以我认为这与 IFS 有关,但我不确定。

【问题讨论】:

  • 您是否介意:echo "${GREP} ${GREP_MY_OPTIONS} \"/home/user/this path has spaces in it/\"*\"/abc.xyz\" | ${GREP} -v :0$",看看将要执行的实际命令是什么?
  • 这产生了:/bin/grep -c -e 2013-01-17 -e 2013-01-18 -e 2013-01-19 -e 2013-01-20 -e 2013-01 -21 -e 2013-01-22 -e 2013-01-23 -e 2013-01-24 -e 2013-01-25 "/home/user/这个路径里面有空格/"*"/abc.xyz " | /bin/grep -v :0$
  • 在风格上,环境变量最好使用大写的变量名,一般使用的变量名使用小写。然后脚本中的 SHOUTING 就更少了。就个人而言,我可能会使用$opts 之类的东西来代替$GREP_MY_OPTIONS;我也尽可能避免在代码中使用“我的”这个词(实际上大多数时候),但这是我的问题。最后(目前),如果我可能需要使用不同的grep 程序,我通常使用:grep="${GREP:-grep}",它允许环境变量 GREP 覆盖默认值。我在测试时使用date 做到了这一点。

标签: arrays bash design-patterns grep ifs


【解决方案1】:

如果你想grep一组路径中的一些内容,你可以这样做:

find <directory> -type f -print0 |
    grep "/home/user/this path has spaces in it/\"*\"/abc.xyz" |
    xargs -I {} grep <your_options> -f <patterns> {}

所以&lt;patterns&gt; 是一个文件,其中包含您要在directory 的每个文件中搜索的模式。

考虑到您的回答,这将满足您的要求:

find "/path\ with\ spaces/" -type f | xargs -I {} grep -H -c -e 2013-01-17 {}

来自man grep:

   -H, --with-filename
          Print  the  file  name for each match.  This is the default when
          there is more than one file to search.

由于您想将元素插入到数组中,您可以执行以下操作:

IFS=$'\n'; array=( $(find "/path\ with\ spaces/" -type f -print0 |
    xargs -I {} grep -H -c -e 2013-01-17 "{}") )

然后将值用作:

echo ${array[0]}
echo ${array[1]}
echo ${array[...]}

当使用变量传递参数时,使用eval 来评估整行。执行以下操作:

parameters="-H -c"
eval "grep ${parameters} file"

【讨论】:

  • 感谢您的帮助 Rubens,我是 bash 和 grep 以及 Linux 的新手。我正在尝试使用您的 find 命令,但我在路径的通配符部分苦苦挣扎,“find”抱怨“没有这样的文件或目录”。
  • @user1464409 不客气;我已经编辑了命令,以便您可以过滤您想要的“路径”,只考虑那些与/home/user/this path has spaces in it/"*"/abc.xyz 匹配的路径。看看这是否有效。 (注意没有实际的换行符,它只是为了避免滚动条)。
  • 好的,我已将其简化为:find /path\ with\ spaces/ -type f | xargs -I {} grep -c -e 2013-01-17 {} 上面的证明是有问题的,也许太复杂了。现在我从 grep 输出中收到的只是匹配的数量。我需要文件名和匹配数(之前报告为:filename:no_of_matches)
  • 在我上次的评论中应该是 filename:count_number。
  • 发生这种情况是因为您将文件路径提供给grep,所以它认为您已经知道计数指的是哪个文件;如果你给出一个列表,它,是的,会识别每个文件。不过,您可以强制打印文件名,正如我在编辑中添加的那样。
【解决方案2】:

你可以做一件事而不会使事情变得复杂:

首先在脚本中更改目录,如下所示:

cd /home/user/this\ path\ has\ spaces\ in\ it/
$ pwd
/home/user/this path has spaces in it

或

$ cd "/home/user/this path has spaces in it/"
$ pwd
/home/user/this path has spaces in it

然后在你的脚本中做任何你想做的事情。

$(${GREP} ${GREP_MY_OPTIONS} */abc.xyz)

编辑:

[sgeorge@sgeorge-ld stack1]$ ls -l
total 4
drwxr-xr-x 2 sgeorge eng 4096 Jan 19 06:05 test tesd
[sgeorge@sgeorge-ld stack1]$ cat test\ tesd/file 
SUKU
[sgeorge@sgeorge-ld stack1]$ grep SUKU */file
SUKU

编辑:

[sgeorge@sgeorge-ld stack1]$ find */* -print | xargs -I {} grep SUKU {}
SUKU

【讨论】:

  • 这似乎是一个不错的简单解决方案,但如果 * 返回的内容也包含空格会怎样?
  • 也感谢您对 Suku 的帮助。我已经尝试实现您建议的“cd 技巧”,但是当我尝试从 MYARRAY 中读取项目时它也失败了(使用 for i in "${MYARRAY[@]}" do echo $i done)。当我回显内容时,它会再次在路径中的任何空格处拆分。
【解决方案3】:

如果您将 GREP_MY_OPTIONS 构建为数组而不是简单字符串,则可以使原始大纲脚本正常工作:

#!/bin/bash
path="/home/user/this path has spaces in it"
GREP="$(which grep)"
GREP_MY_OPTIONS=("-c")
j=1
for i in {-2..2}
do
    GREP_MY_OPTIONS[$((j++))]="-e"
    GREP_MY_OPTIONS[$((j++))]=$(date --date="$i day" +'%Y-%m-%d')
done

IFS=$'\n'
MYARRAY=( $(${GREP} "${GREP_MY_OPTIONS[@]}" "$path/"*"/abc.xyz" | ${GREP} -v :0$ ) )

我不清楚你为什么使用GREP="$(which grep)",因为你将执行相同的grep,就像你直接写grep一样——除非,我想,你有grep的别名(然后是问题;不要别名grep)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2022-10-17
    • 2014-11-20
    相关资源
    最近更新 更多