如果文件中不存在这些行,如何将多行附加到文件中?
例如,要添加多个全局别名,/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
我被批评说这个操作不包括检查行是否已经存在的方法,如果错误地重新执行 heredocument,我可能会导致冗余以及冲突。
用于将文件中的行添加
newdata
到datafile
. 更改newdata
为 here-doc 应该很简单。这实际上不是很有效,因为它需要grep
每个(新)输入行:对于每一行,我们使用
grep
它来查看它是否已经存在于目标文件中,-F
用于固定字符串匹配(无正则表达式),-x
用于全行匹配,并-q
抑制匹配行的输出。grep
如果没有找到匹配的行,则返回虚假错误代码,因此如果否定结果为真,则附加到目标文件。更有效地,在
awk
. 这依赖于awk
能够将任意行作为数组的键来处理。第一部分
FNR == NR { lines[$0] = 1; next }
将第一个输入文件的所有行作为键加载到(关联)数组lines
中。第二部分! ($0 in lines) {print}
在以下输入行上运行,如果该行不在数组中,则打印该行,即“新”行。结果输出仅包含新行,因此需要将其附加到原始文件中,例如
sponge
:或者我们可以
awk
将这些行附加到最后一行,它只需要将文件名传递给awk
:要将 here-doc 与 一起使用,除了设置重定向之外
awk
,我们还需要将(stdin) 添加为显式源文件,因此-
awk ... "$target" - <<EOF
该解决方案可能与您的想法略有不同,但我会检查是否实际定义了别名,如果没有,则仅将其添加到 bashrc 中。假设您使用的是相对最新的 Bash 版本...
源它
. ./scriptname
而不是作为普通脚本运行它。注意:如果您有一堆候选别名并且对手动将它们转换为关联数组形式持谨慎态度,那么您可以使用编辑文件
vim
并运行以下命令::%s/\valias *([^=]+)\=['"]?([^'"]+)['"]?$/aliases['\1']='\2'/
.或将您的候选别名(仅此而已)放在一个文件中(例如
/tmp/aliases.txt
),然后aliases[..]='..'
将脚本中的行替换为:当然,除了使用 AA 之外,还有其他方法,但它们干净且易于使用……我现在全力以赴。:)
完全匹配的通用解决方案(未针对性能进行优化);该文件
input
包含要检查的行:测试:
命令的输出
awk
:嗯。这个怎么样...
将别名添加到文件new中。然后...
我们对新别名和bashrc内容进行唯一排序(放入临时文件以避免在追加到bashrc时出现竞争条件)并通过
comm
.comm
对已排序的文件进行逐行比较,并显示唯一和常见的行。我们抑制了第 2 列和第 3 列 (-23
),因此结果只是那些对new唯一的行,我们将它们附加到bashrc。而已。(这是一种与我的其他答案完全不同的方法,专注于您对更多“单线”的追求。)
附加行的顺序重要吗?
如果没有,您可以尝试这样的解决方案:
假设您以前保存了要添加到文件中的行
aliases
。comm
是 GNU coreutil(您可以查看它的手册页),它允许逐行比较两个已排序的文件。