awk每个文件更改一次

awk每个文件更改一次,awk,gawk,Awk,Gawk,有没有更优雅的方法?一些我错过的内置结构?我正在运行GNU Awk 4.1.0(我非常高兴-我在原地)。你可以说: awk -i inplace ' BEGIN {FS=" "} BEGINFILE {changed=0} { print;if ($1 == "namespace" && !changed) {print "foo";changed=1} } ' * 甚至: ... -F' ' '$1 == "namespace" && !a {$

有没有更优雅的方法?一些我错过的内置结构?我正在运行GNU Awk 4.1.0(我非常高兴-我在原地)。

你可以说:

awk -i inplace '
  BEGIN {FS=" "}
  BEGINFILE {changed=0} 
  { print;if ($1 == "namespace" && !changed) {print "foo";changed=1} }
' *
甚至:

... -F' ' '$1 == "namespace" && !a {$0=$0 RS "foo";a=1}1' file
正如上面评论中提到的,这与您所写的非常相似,只是它使用
RS
变量插入文本


要对多个文件执行此操作,需要重置变量:

... -F' ' '$1 == "namespace" && !_ {$0=$0 RS "foo";_=1}1' file


FS=”“
是默认值,无需显式指定。

您当然可以编写它以使其略短一些,但我猜逻辑会类似。我对较短的版本很好奇。我总是渴望学习:)我明白了,你在用我不熟悉的东西。但是最后的1是什么呢?天哪,1是一个表达式,模式可以是空的?这基本上是
{print}
的简写。超级棘手。@chx Right
1
打印的缩写。您可能还会看到一些人改用
42
!Hrm这将总共执行一次,而不是每个文件执行一次。@chx Right,要对多个文件执行它,您需要在开始时将变量重置为0。请参见上面的编辑。这非常棘手。ARGIND是ARGV中文件名的索引,因此每个文件都会更改,我假设未初始化的变量为空,否定的变为true ish,递增的和否定的变为false ish,因此每个文件都会触发一次。这并不复杂,只是习惯用法。以这种方式使用名为
seen[]
的数组是一种非常常见的awk习惯用法,它只对任何事物的第一次出现进行操作。是,ARGIND是当前正在处理的文件的ARGV数组中的仅gawk索引。您可以使用FILENAME,但如果同一个文件在arg列表中多次出现,则会有不同的语义<代码>可见[x]+
在第一次计算时为假,因为
可见[x]
开始时为
零或空
然后后递增,因此以后每次
可见[x]+
都为真<代码>!所见的[x]+是相反的-第一次为true,之后为false。
... -F' ' 'BEGINFILE {a=0} $1 == "namespace" && !a {$0=$0 RS "foo";a=1}1' *
... -F' ' 'FNR==1 {a=0} $1 == "namespace" && !a {$0=$0 RS "foo";a=1}1' *
awk -i inplace '$1=="namespace" && !seen[ARGIND]++ {$0=$0 ORS "foo"} 1' *