我正在尝试编写一个 bash 脚本来检查多个文件中的某个字符串,然后如果找到该字符串则将其删除。这是我所拥有的,我认为它会起作用,但只是部分起作用。文件中的条目将被删除,但第二次运行时,我没有收到“无事可做...”消息。
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck="for f in ${files[*]}; do cat $f | grep blah | wc -l; done"
#for f in ${files[*]}; do cat $f | grep collector.acuity.com | wc -l; done
if [[ "$tmpcheck" != 1 ]];then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi
任何帮助都会有很大帮助。
答案1
tmpcheck
其他答案中已经指出了代码中的主要问题(对 的分配)。这是一种稍微不同的方法,假设打印出已修改/未修改文件的名称不是强制性的:
if grep -q -- blah "${files[@]}"
then
sed -i -e '/blah/d' -- "${files[@]}"
systemctl restart rsyslog.service
else
printf '%s\n' 'Nothing to do'
fi
这里的主要想法是:
- 除非必要,否则在复合命令中直接使用命令的 (
grep
) 退出状态if
,而不是存储其输出并稍后进行测试; - 在循环中调用实用程序效率较低;最好尽可能使用多个文件作为参数来调用它们。
另外,虽然这些不是您显示的代码中的问题:
- 添加选项结束标记 (
--
) 可防止出现不常见的文件名; printf
更安全比echo
,尤其是在打印扩展结果时。
答案2
我想你想检查 for 循环内的废话。不需要 tmpcheck 变量。相反,您可以$restartrsyslog
仅重新启动 rsyslog 一次:
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
restartrsyslog=
for f in "${files[@]}";do
if grep -q blah "$f"; then
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
restartrsyslog=yes
else
echo -e "Nothing to do, blah has been removed from $f"
fi
done
if [[ -n $restartrsyslog ]] ; then
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
fi
答案3
您的tmpcheck
变量被设置为命令而不是该命令的输出,它永远不会等于 1,因此表达式将始终计算为 true。您应该使用该$( ... )
构造来替换命令的输出。您也不需要循环遍历文件,但如果这样做,您不应该使用${files[*]}
而应该使用${files[@]}
。此外,不需要通过cat
管道进入单个文件,grep
因为grep
可以读取文件,也不需要通过管道grep
进入,wc -l
因为grep
可以-c
选择对结果进行计数。最后你为什么要检查它tmpcheck
不等于1?如果等于2或更大怎么办?
这对你有用吗?
#!/bin/bash
files=(
'/etc/rsyslog.conf'
'/etc/rsyslog.d/remote.conf'
'/etc/rsyslog.d/01-remote.conf'
)
tmpcheck=$(cat "${files[@]}" | grep -c blah)
if (($tmpcheck>=1)); then
for f in "${files[@]}";do
echo -e "Removing blah from $f"
sed -i "/blah/d" "$f"
done
echo -e "Restarting rsyslog service"
systemctl restart rsyslog.service
else
echo -e "Nothing to do, blah has been removed from $f"
fi