我有一个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
任何和所有帮助都非常感谢让它发挥作用。
问候,
影
答案 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