避免 fgrep 字符串中的全局扩展

避免 fgrep 字符串中的全局扩展

我正在开发一个缺少该crontab命令的 Busybox 发行版。我想创建一个 bash 脚本,用文本文件中列出的作业更新 root 的 crontab 文件。我已经让大部分脚本正常工作,除了当我尝试使用 fgrep 在 cron 文件中查找作业时,它会将字符扩展*为全局变量并破坏所有内容。

# Notes: CRONJOBS_LIST is the text file containing new jobs.
#        CRONJOBS_DIR is the directory where the new jobs will be installed.
#        CRONTAB_FILE is /etc/cron/crontabs/[user].

# Find each job in the crontab file. If not found, append it.
while read -r job; do
    if ! fgrep -q "$job" "$CRONTAB_FILE"; then
        # Appending file in loop avoids adding duplicate jobs if any are found in list
        echo "$job" >> "$CRONTAB_FILE"
        echo "Added '$job' to $CRONTAB_FILE"
    else
        echo "'$job' already found in $CRONTAB_FILE"
    fi
# Replace variable references in job list with correct paths
done < <(sed -e "s|\$CRONJOBS_DIR|$CRONJOBS_DIR|" "$CRONJOBS_LIST")

任何人都可以帮我修复脚本,这样一行CRONJOBS_LIST

2 0 * * * bash $CRONJOBS_DIR/sysbak.sh backup

将被 grep 而不将*s 扩展为全局变量?

答案1

如果我明白您要做什么,您想将 file 中的行添加$ADD到 file $TARGET,但不添加已经存在的行?

我认为可能有比重复 grep 更简单的方法。comm可以给你只存在于第一个、第二个或两个文件中的行,所以让我们使用它:

comm -23 <(sort "$ADD") <(sort "$TARGET") > tmp ; cat tmp >> "$TARGET"

该论证的-23意思是不是显示仅存在于文件 2 中的行,并不是显示两者中存在的行 (3)。输入必须进行排序,为了安全起见,我通过临时文件进行附加。

一个暴力解决方案与sortuniq可能有效......

cat "$ADD" "$TARGET" | sort | uniq > tmp ; mv tmp "$TARGET"

这当然会对结果文件进行排序(并删除任何先前存在的重复行)。

(当然你可能想要制作更多唯一的临时文件名.)


至于现在的代码,我认为 的条件fgrep是相反的,因为grep如果找到匹配则返回 0,并且与大多数编程环境不同,零在 shell 脚本中充当 true 。也 something | while read ...应该工作相同,while... < <(something)但可能更容易阅读。

相关内容