2013-01-19 23 views
4

我正在努力传递包含在变量中的几个grep模式。这是我的代码:使用变量在bash中传递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模式搜索包含空格的路径中的几个文件,并把它们在ARR唉

当我使用“回声$ GREP_MY_OPTIONS”这也带来我所期待的,但是当我运行该脚本,它失败的错误:

/斌/ grep的:无效选项 - “”

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

+0

你会介意做:'echo“$ {GREP} $ {GREP_MY_OPTIONS} \”/ home/user /此路径中有空格/ \“* \”/ abc.xyz \“| $ {GREP} -v:0 $“',看看将要执行的实际命令是什么? – Rubens

+0

This produced: /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 $ – user1464409

+0

从文体上讲,最好对环境变量使用大写变量名称,并使用小写变量名称作为通用名称。脚本中的SHOUTING较少。就个人而言,我可能会使用'$ opts'来代替'$ GREP_MY_OPTIONS';我尽可能避免使用代码中的“我的”一词(实际上大部分时间),但这是我的问题。最后(现在),如果我可能需要使用不同的'grep'程序,我通常使用:'grep =“$ {GREP:-grep}”'这允许环境变量GREP覆盖缺省值。测试时我用'date'做了。 –

回答

1

如果构建了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)。

3

如果你想grep在一组路径一些内容,你可以做到以下几点:

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

这样<patterns>是包含你想从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" 
+0

感谢您的帮助Rubens,我是bash和grep以及Linux的新手。我试图使用你的find命令,但我正在努力处理通配符的一部分,“find”正在抱怨“没有这样的文件或目录”。 – user1464409

+0

@ user1464409你非常欢迎;我编辑了这个命令,以便你可以过滤你想要的“路径”,只考虑那些匹配'/ home/user /这个路径中有空格/“*”/ abc.xyz'的路径。看看是否有效。 (请注意,没有实际的换行符,它只是为了避免滚动条)。 – Rubens

+0

好的,我把这个做了简化: find/path \ with \ spaces/-type f | xargs -I {} grep -c -e 2013-01-17 {} 如上所述证明存在问题并且可能太复杂。现在我从grep输出中收到的是匹配的数量。我需要的文件名和匹配数(以前报告为:文件名:no_of_matches) – user1464409

0

你可以做一件事而不让事情复杂:

首先做了更改目录在脚本中像下面:

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) 

编辑

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

编辑

[[email protected] stack1]$ find */* -print | xargs -I {} grep SUKU {} 
SUKU 
+0

这似乎是一个很好的简单解决方案,但如果*返回的内容还包含空格会发生什么? – user1464409

+0

查看我的最后编辑 – Suku

+0

感谢您的帮助Suku。我尝试过实施你所建议的“cd技巧”,但是当我尝试从MYARRAY中读取项目时(使用“$ {MYARRAY [@]}”做echo $ i),它也失败了。当我回显内容时,它会再次在路径中的任何空格处分割。 – user1464409