ls |脚本中的grep -v

时间:2012-05-07 08:19:35

标签: bash grep

我有一个bash脚本,我想这样做

    (in pseudo)
    for each item in excludelist
        append to string: | grep -v $item

    for each file in directory 
    do
        stuff
    done

现在

   (in real code, the creation and concatenation of f works, the problem is not here I believe)
   for i in $EXCLUDE
   do
       echo $i
       f="$f | grep -v $i"
   done

   for d in `ls $AWSTATSCONF/awstats*conf $f`
   do
       echo $d
   done

输出

   ls: |: No such file or directory
   ls: grep: No such file or directory

任何和所有帮助都非常感谢让它发挥作用。

问候,

5 个答案:

答案 0 :(得分:2)

由于您使用的是bash,因此可以使用pattern matching排除您的EXCLUDE列表:

pattern=$(awk ' BEGIN {OFS="|"; printf("!(")} 
                {$1=$1; printf("%s",$0)} 
                END {print ")"}
              ' <<< $EXCLUDE)
shopt -s extglob
for d in $pattern; do
  echo $d
done    

答案 1 :(得分:2)

有很多方法可以解决它。

正确地,对解析ls的输出存在疑虑。这些是多么合理取决于你是否必须处理所有可能的文件名(包含空格和换行符的文件名特别有问题),或者你是否有正常的文件名只使用可移植文件名字符集(根据{{3是(拉丁语)字母,数字,加.-_)。

假设您只需要处理可移植文件名,那么您可以获得所需的效果:

for i in $EXCLUDE
do
    echo $i
    f="$f | grep -v $i"
done

for d in `eval ls $AWSTATSCONF/awstats*conf $f`
do
    echo $d
done

使用eval强制shell将字符串$f中的管道视为shell中的管道。 小心eval是一个强大而又危险的工具。

如果要排除20个术语,则选择按顺序运行20个greps的机制使用大量进程。对于演示目的而言,它可能不会太严重,但如果你正在处理生产工作和成千上万的文件......那就不太好了。

您可能希望查看构建egrep(或grep -E)命令:

f="antidisestablishmentarianism"
for i in $EXCLUDE
do
    f="$f|$i"
done

ls $AWSTATSCONF/awstats*conf |
egrep -v "$f" |
while read d
do echo $d
done

我假设你没有任何名字包含'antidisestablishmentarianism'的名字文件潜伏着(是的,这是一个真实的词;但它主要用作笑话)。

while read公式是编写for循环的另一种方式。警惕不能影响父shell变量的子进程。也就是说,while循环由子shell处理,而不是主shell处理,所以如果依靠循环在主shell中设置变量,它将无法工作 - 你可以/应该回到for循环。但是,您不需要再次eval

for d in $(ls $AWSTATSCONF/awstat*conf | egrep -v "$f")
do
    echo $d
done

使用$(...)代替后引号通常是一个好主意。

答案 2 :(得分:0)

您需要将grep的*输出附加到$f

$f = "$f $(grep -v $i)"

答案 3 :(得分:0)

问题是foo whatever whatever else作为ls命令的普通转义参数执行(当然|并且在当前目录中找不到grep)。 eval是将字符串作为bash命令执行的命令

您需要执行以下操作

for d in `eval "ls $AWSTATSCONF/awstats*conf $f"`
do
   echo $d
done

请记住,这会明智地打开一大堆蠕虫,检查以下FAQ以了解更多内容并了解其他替代方案

答案 4 :(得分:0)

请勿使用for i in $(ls)。你应该使用globbing。

不要使用连接来构建grep -v的长字符串。

$EXCLUDE来自哪里?它应该是一个数组而不是一个字符串。

for d in "$AWSTATSCONF"/awstats*conf
do
    for e in "${exclude[@]}"
    do
        if [[ $d != $e ]]
        then
            echo "$d"
        fi
    done
done