我想添加一行
allow = alaw
在字符串之前
nat = no
在文件sip.conf
(或任何基于文本的文件)中。如果allow = alaw
之前已经存在,nat = no
则不应添加。并且该行不应添加在紧接该文件的[general]
和后面的两个部分中[providertrunk0]
。
文件内容示例:
[general]
disallow = all
allow = ulaw
nat = no
[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no
secret =
nat = no
progressinband = yes
allow = ulaw
allow = alaw
nat = no
progressinband = yes
disallow = all
allow = ulaw
nat = no
progressinband = yes
更改后将是
[general]
disallow = all
allow = ulaw
nat = no
[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no
secret =
allow = alaw
nat = no
progressinband = yes
allow = ulaw
allow = alaw
nat = no
progressinband = yes
disallow = all
allow = ulaw
allow = alaw
nat = no
progressinband = yes
我的尝试
我试图排除[general]
和[providertrunk0]
部分的整个过程,但应用于整个文件,使用'/general/,/providertrunk0/{next}'
如下:
awk -v add="allow = alaw" '/general/,/providertrunk0/{next} /^nat = no$/&&lastLine!=add{print add}{lastLine=$0}1' sip.conf '
但它没有给出正确的输出。
答案1
$ cat tst.awk
BEGIN {
RS=""; ORS="\n\n"; FS=OFS="\n"
skip["[general]"]
skip["[providertrunk0]"]
add = "allow = alaw"
tgt = "nat = no"
}
!($1 in skip) {
for (i=1; i<NF; i++) {
if ( ($i != add) && ($(i+1) == tgt) ) {
$i = $i OFS add
}
}
}
{ print }
。
$ awk -f tst.awk file
[general]
disallow = all
allow = ulaw
nat = no
[providertrunk0]
disallow = all
allow = ulaw
;allow = alaw
nat = no
secret =
allow = alaw
nat = no
progressinband = yes
allow = ulaw
allow = alaw
nat = no
progressinband = yes
disallow = all
allow = ulaw
allow = alaw
nat = no
progressinband = yes
将 RS 设置为 null 会使 awk 处于段落模式(请RS = ""
参阅https://www.gnu.org/software/gawk/manual/gawk.html#Multiple-Line)因此您的输入被分成由空行分隔的多行记录。设置 ORS="\n\n" 可确保输出时记录之间有一个空行。将 FS 和 OFS 设置为“\n”表示记录被拆分为字段。因此,其余的代码就很简单了,因为您只需将特定字段(行)与问题中提到的值进行比较即可。skip[]
只是我为存储第一个字段(第一行)字符串的任何数组编写的名称,我想忽略该字符串以便在该数组中进行进一步处理,然后对于每个记录测试,如果记录的第一个字段/行位于数组,如果是,则跳过对其进行处理。