![用于顺序替换模式的 awk 查询](https://linux22.com/image/150275/%E7%94%A8%E4%BA%8E%E9%A1%BA%E5%BA%8F%E6%9B%BF%E6%8D%A2%E6%A8%A1%E5%BC%8F%E7%9A%84%20awk%20%E6%9F%A5%E8%AF%A2.png)
我发现下面的 awk 命令可以顺序替换文件中的特定行,但我想知道这是如何工作的。
输入:-
DS: 1
DS: 1
DS: 1
DS: 1
DS: 1
DS: 1
DS: 1
输出:-
DS: 1
DS: 2
DS: 3
DS: 1
DS: 2
DS: 3
DS: 1
DS: 2
DS: 3
awk 命令:-
awk '$1 ~ /DS:/ {$NF=((c++ % count) + 1)} 1' count=3
答案1
我有理由相信工作awk
命令是
awk -v count=3 '/DS:/ {$NF=((c++ % count) + 1)} 1' input
input
输入文件在哪里。另外,我认为输入文件中应该有 9 行而不是 7 行来生成问题中指定的输出。
下面是它的工作原理。
首先,该选项-v count=3
分配3
给awk
多变的 count
。如果它按照问题中的方式编写(count=3
在命令末尾),3
将被分配给外壳变量并且 无法被访问,awk
并且会导致被零除错误,因为count
将被隐式初始化为0
。
在
/DS:/ {$NF=((c++ % count) + 1)}
该/DS:/
部分是大括号中的块的条件。它代表正则表达式DS:
,只能匹配字符串DS:
。此条件匹配所有包含 的行DS:
。
对于所有这些行,变量c
都会递增,然后取模count
。由于我们没有对该c
变量进行显式定义,因此它会隐式初始化0
为该代码块首次执行时的值。
然后将结果添加到1
并分配给$NF
。这里,NF
是由字段分隔符分隔的行中的字段数。默认字段分隔符 ( FS
) 是空格。请注意,空格FS
是一种特殊情况awk
,多个连续空格将被视为仅一个字段分隔符。
由于NF
是字段数,$NF
因此指最后一个字段。在这种情况下,对 的赋值$NF
导致 被1
替换为通过评估 获得的值((c++ % count) + 1)
。
Final1
代表 true 条件,其后面的代码块被省略。print
当条件为真时,其效果是隐含的。由于1
始终为 true,因此始终会执行该操作并打印当前行,可能是在最后一个块转换之后。
为了更好地理解该过程,我们可以跟踪awk
.awk
有一个隐式循环,可以循环输入的行。
第一行:
c
隐式赋值0
。c++
仍然是0
,但它更改c
为1
,(c++ % count)
is0
模,3
所以 is0
,((c++ % count)+1)
is1
,赋值将最后一个字段(在本例中也恰好是最后一个字符)更改为1
,最终1
打印此行,所以我们得到DS: 1
。第二行:
c
现在1
。((c++ % count)+1)
是2
并更改c
为2
.最后一个字段更改为2
并打印,因此我们得到DS: 2
。第三行:类似地,
((c++ % count)+1)
更改c
为3
并计算为3
。我们得到DS: 3
.第四行:现在是
%
真正生效的时候。(c++ %count)
是3
取模,3
等于0
,并再次((c++%count)+1)
计算为1
。我们得到DS: 1
.
等等。这就是它的工作原理。请注意,如果有任何行没有,DS:
它们将被逐字打印。