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)
我被批评说这个操作不包括检查行是否已经存在的方法,如果错误地重新执行这里文档,我可能会导致冗余和冲突。
简单的 shell 脚本,用于将文件中的行添加newdata
到datafile
. newdata
更改为此处文档应该很简单。这实际上不是很有效,因为它需要grep
每个(新的)输入行:
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
如果找不到匹配行,则返回虚假错误代码,因此如果否定结果为真,则附加到目标文件。
更有效的是,在awk
. 这依赖于awk
能够将任意行处理为数组的键。
$ 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}
在以下输入行上运行,如果该行不在数组中,则打印该行,即“新”行。
生成的输出仅包含新行,因此需要将其附加到原始文件,例如sponge
:
$ 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
:
$\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