Bash 脚本中的ls | grep-v

Bash 脚本中的ls | grep-v,bash,grep,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 prob

我有一个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
任何和所有的帮助,真的很感谢让这个工作

您好


Shadow

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

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

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

您需要执行以下操作

for d in `eval "ls $AWSTATSCONF/awstats*conf $f"`
do
   echo $d
done
请记住,从安全角度来看,这将打开一大罐蠕虫,请检查以下内容以了解更多信息,并了解其他替代方法

不要将
用于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

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

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

有很多方法可以解决这个问题

正确地说,对于解析
ls
的输出存在疑虑。这些疑虑的合理性取决于您是否必须处理所有可能的文件名(包含空格和换行符的文件名特别有问题),或者您是否有只使用可移植文件名字符集的普通文件名(根据,它们是(拉丁)字母表、数字加上
-

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

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
)命令:

我假设您没有任何名称包含“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

使用
$(…)
而不是反引号通常是一个好主意。

f=$(echo“$f”| grep-v“$i”)
工作得更好?但那部分工作得更好。问题在于ls的执行。考虑到
ls
尝试访问“
grep
”,我认为那部分工作得不太好。我的意思是,构建包含“grep-v”系列的字符串's工作得很好。我确实意识到将它添加到ls命令中是不起作用的。
$f
到底是什么意思?我没有将它设置在任何地方。我相信我的问题是编错了。我认为问题的部分是ls,而不是greps的创建。没问题。它仅供专业人士内部使用。没有web前端或类似的是的。但是感谢您的警告:-)EXCLUDE=“string1 string2 string3”
for d in $(ls $AWSTATSCONF/awstat*conf | egrep -v "$f")
do
    echo $d
done