如果文件中不存在这些行,如何将多行追加到文件中?

Arc*_*ing 4 shell-script text-processing deduplication

如果文件中不存在这些行,如何将多行追加到文件中?

例如,要添加多个全局别名,/etc/bash.bashrc我使用heredocument

cat <<-"BASHRC" >> /etc/bash.bashrc
    alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
    alias brc="nano /etc/bash.bashrc"
BASHRC
Run Code Online (Sandbox Code Playgroud)

我被批评说这个操作不包括检查行是否已经存在的方法,如果错误地重新执行这里文档,我可能会导致冗余和冲突。

ilk*_*chu 5

简单的 shell 脚本,用于将文件中的行添加newdatadatafile. newdata更改为此处文档应该很简单。这实际上不是很有效,因为它需要grep每个(新的)输入行:

\n\n
target=datafile\nwhile IFS= read -r line ; do\n    if ! grep -Fqxe "$line" "$target" ; then\n        printf "%s\\n" "$line" >> "$target"\n    fi\ndone < newdata \n
Run Code Online (Sandbox Code Playgroud)\n\n

对于每一行,我们用于grep查看它是否已存在于目标文件中、-F用于固定字符串匹配(无正则表达式)、-x用于全行匹配以及-q抑制匹配行的输出。grep如果找不到匹配行,则返回虚假错误代码,因此如果否定结果为真,则附加到目标文件。

\n\n
\n\n

更有效的是,在awk. 这依赖于awk能够将任意行处理为数组的键。

\n\n
$ awk \'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}\' datafile newdata \n
Run Code Online (Sandbox Code Playgroud)\n\n

第一部分FNR == NR { lines[$0] = 1; next }将第一个输入文件的所有行作为键加载到(关联)数组中lines。第二部分! ($0 in lines) {print}在以下输入行上运行,如果该行不在数组中,则打印该行,即“新”行。

\n\n

生成的输出仅包含新行,因此需要将其附加到原始文件,例如sponge

\n\n
$ awk \'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}\' datafile newdata |\xc2\xa0sponge -a datafile\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者我们可以将awk这些行附加到最后一行,它只需要将文件名传递给awk

\n\n
$\xc2\xa0target=datafile \n$ awk -vtarget="$target" \'FNR == NR { lines[$0] = 1; next } \n                        ! ($0 in lines) {print >> target}\' "$target" newdata\n
Run Code Online (Sandbox Code Playgroud)\n\n

要将here-doc与 一起使用,除了设置重定向之外,awk我们还需要添加(stdin)作为显式源文件,因此-awk ... "$target" - <<EOF

\n