我有一个文件,需要在 Linux 的多个位置添加标头。 “标题”是一个文件,我只能将其添加到第一行;这很好,但我现在想在多个位置添加相同的标头;特别是在找到新的 IP 地址之前。我实际上不需要带有标题的文件;在获得所有输出后,我只需通过 awk 或 sed 添加文本即可。
需要在找到新 IP 地址后准确插入标头。
该列表是可变的;例如,在 ip 192.168.10.10 处,有 3 个条目,但可能更多;例如,对于 ip 192.168.10.33,有 2 个条目,但可能更多。默认情况下端口已经排序;但 IP 地址尚未排序,但已分组。
输出看起来像:
192.168.10.10 1/1/2
192.168.10.10 1/1/3
192.168.10.10 1/1/4
192.168.10.33 1/1/2
192.168.10.33 1/1/6
192.168.10.20 1/1/6
192.168.10.20 1/1/7
192.168.10.20 1/1/10
192.168.10.20 1/1/18
我希望输出看起来像这样:
SWITCH ID PORT
192.168.10.10 1/1/2
192.168.10.10 1/1/3
192.168.10.10 1/1/4
SWITCH ID PORT
192.168.10.33 1/1/2
192.168.10.33 1/1/6
SWITCH ID PORT
192.168.10.20 1/1/6
192.168.10.20 1/1/7
192.168.10.20 1/1/10
192.168.10.20 1/1/18
答案1
这是相当冗长的 awk 脚本,它添加了标头
NR==1 {
print "SWITCH ID PORT"
print $0
prev=$1
next
}
$1!=prev {
print ""
print "SWITCH ID PORT"
print $0
prev=$1
next
}
$1==prev {
print $0
}
将其保存到文件中。例如addheader.awk
像这样调用
awk -f addheader.awk inputfile
或者像这样
commandproducinginput | awk -f addheader.awk
脚本的解释
awk 的工作原理大致如下:
for every line of input
for every rule
if condition is true
execute code block
“规则”是一对条件和代码块。
上面代码中的规则示例
NR==1 {
print "SWITCH ID PORT"
print $0
prev=$1
next
}
这NR==1
就是条件。大括号中的部分{...}
是代码块。
NR
是一个 awk 特定变量,包含行号(准确地说是记录号)。所以NR==1
仅在第一行是正确的。
在第一行我们打印标题行。然后打印实际行($0
是当前行的 awk 变量)。然后记住这一行的IP地址($1
是当前行第一个字段的awk变量)。然后我们说直接进入下一行,这样 awk 就不会考虑其他规则。你可以想像next
一个break
跳出循环for every rule
。
$1!=prev
如果当前 IP 地址与前一个地址不匹配,则下一条规则的条件为 true。在这种情况下,我们打印一个空行。然后是标题。然后是线路本身。然后记住这个新的IP地址。然后转到下一行。
最后一条规则是“默认情况”。如果 IP 地址与之前的相同,则按原样打印该行。
next
前面的规则有效地形成了一个 if else if 链。
在伪代码中,它看起来大致像这样
for every line:
if is first line:
print header then line
else if IP adress is different than previous:
print empty line then header then line
else if IP adress is same to previous:
print line
奖金:
以下变体是等效的
省略最后一个代码块
NR==1 {
print "SWITCH ID PORT"
print $0
prev=$1
next
}
$1!=prev {
print ""
print "SWITCH ID PORT"
print $0
prev=$1
next
}
$1==prev
如果代码块丢失,默认操作是按原样打印该行。
或者省略条件但保留代码块
NR==1 {
print "SWITCH ID PORT"
print $0
prev=$1
next
}
$1!=prev {
print ""
print "SWITCH ID PORT"
print $0
prev=$1
next
}
{
print $0
}
如果条件缺失,则隐式为 true。这是可能的,因为next
前面的规则有效地形成了 if else if 链。最后一条规则与最后一条 else 类似,因此不需要任何条件。
重新排列规则
$1==prev
NR==1 {
print "SWITCH ID PORT"
print $0
prev=$1
}
$1!=prev {
print ""
print "SWITCH ID PORT"
print $0
prev=$1
}
像这样我们可以省略next
.但就我的口味而言,它的可读性较差。
将公共代码提取到函数中
func common() {
print "SWITCH ID PORT"
print $0
prev=$1
next
}
NR==1 {
common()
}
$1!=prev {
print ""
common()
}
$1==prev
请注意,所有变量在 awk 中都是全局的。