如何添加或替换文件中可能包含特殊字符的部分行



我想写一个bash脚本,它可以更新/etc/security/limits.conf文件。

该文件可能包含以下内容:

*               soft    core            0
*               hard    rss             10000
@student        hard    nproc           20
@faculty        soft    nproc           20
@faculty        hard    nproc           50
ftp             hard    nproc           0
@student        -       maxlogins       4

假设我想这样运行脚本:

Usage:
update-ulimits <domain> <type> <item> <value>
Examples:
./update-ulimits '*' hard rss 20000
./update-ulimits bob hard nofile 1024

这将更改文件以包含:

*               soft    core            0
*               hard    rss             20000
@student        hard    nproc           20
@faculty        soft    nproc           20
@faculty        hard    nproc           50
ftp             hard    nproc           0
@student        -       maxlogins       4
bob hard nofile 1024

因此,如果文件已经包含一行具有domaintypeitem,它将替换value,否则它将附加一行包含所有4个参数的新行。列不需要对齐。

这是一个特定的例子,其中只有几个元字符需要担心,但我很好奇是否有一个好的解决方案可以处理所有任意的元字符。我猜perl和awk应该能够做到这一点,但我对它们都不太熟悉。

一个awk解决方案:

$ cat update-ulimits
#!/usr/bin/bash
domain="${1}"                                            # OP can add code to verify inputs as needed
ltype="${2}"
item="${3}"
value="${4}"
awk -v dom="${domain}" -v type="${ltype}" -v item="${item}" -v val="${value}" '
($1 == dom)  &&
($2 == type) &&
($3 == item)     { $4 = val ; foundit=1 }                # overwrite field 4
                 { print }                               # print current line
END { if (! foundit) { print dom, type, item, val } }    # if not found, print all inputs as a new line
' limits.conf

几个样本运行:

$ update-ulimits '*' hard rss 20000
*               soft    core            0
* hard rss 20000
@student        hard    nproc           20
@faculty        soft    nproc           20
@faculty        hard    nproc           50
ftp             hard    nproc           0
@student        -       maxlogins       4
$ update-ulimits bob hard nofile 1024
*               soft    core            0
*               hard    rss             10000
@student        hard    nproc           20
@faculty        soft    nproc           20
@faculty        hard    nproc           50
ftp             hard    nproc           0
@student        -       maxlogins       4
bob hard nofile 1024

注意

  • OP可以决定awk是否应该自动覆盖源文件(请参阅-i标志,例如:使用awk将修改保存到位(,或者可能添加额外的代码,在覆盖原始文件之前先保存原始文件
  • 由于向limits.conf添加新行时列对齐不是问题,所以我采取了简单的方法,不必为修改后的行维护空白;如果需要保留原始空白,请查看"如何在awk中保留字段之间的原始空白?"的答案

这不是一个好主意。如何选择要编辑的行?唯一真正的方法是指定一个匹配表达式,然后指定一个替换行/字段。即便如此,您也可能有多个匹配项。

一种更快的方法是只打印每行带数字的行,并让用户选择一行进行编辑。此时,您还可以在文本编辑器中打开它。

我的建议是学习sedawk。然后,无论何时需要对文件执行特定的编辑工作,都可以。

编辑-如果你只想替换一个值:

sed -E s'/(^<match-fields>s+)([0-9]+s*$)/1<new-number>/'

最新更新