以下命令会产生相同的答案:
tail -n 1 ~/watchip.sh.csv | awk 'BEGIN { FS = "," } ; { print $1 }'
tail -n 1 ~/watchip.sh.csv | awk '{ FS = "," } ; { print $1 }'
编辑:自从发布这个问题以来,我了解到我的断言上面的两个命令产生相同的答案是不正确的。至少一般而言不是。因此,上面的命令似乎是何时
BEGIN
需要语句的示例。对于造成的混乱表示歉意。
我不是经验丰富的awk
用户,但试图通过使用和阅读文档来更好地处理它。但我在 BEGIN 和 END 上读到的所有内容都是模糊的(对我来说没有什么意义)。也许这是因为我只awk
在非常有限的情况下使用过。
有人可以简要解释一下 BEGIN 语句何时会是必需的在awk
?
答案1
当您确实想要执行某些操作时,通常使用BEGIN
andEND
子句awk
前和后对文件的实际处理分别发生。因此,通过此逻辑,其中的语句/操作对于给定的输入文件仅执行一次。
一般会进行什么类型的动作BEGIN
?
初始化用于分割行输入的特殊变量,即输入和输出字段分隔符
FS
。OFS
尽管人们总是可以使用构造来定义这些特殊变量-v FS=
或通过正则表达式运算符来定义它,-F','
但这样做时可读性要强得多。从您的示例来看,必须{ FS="," }
在 的正文中定义awk
是相当多余的,因为它会为输入文件的每一行初始化变量。例如,如果您的行包含 n 行,则初始化会发生 n 次。echo "1,2,3" | awk 'BEGIN {FS=OFS=","} {print $1}'
为从脚本正文生成的输出定义自定义标题行
awk
。例如,在前面的示例中,我想打印一个标题,表示我正在打印第一列值echo "1,2,3" | awk 'BEGIN {FS=OFS=","; print "First column values only"} {print $1}'
(可选 - 仅为了可读性) - 您还可以初始化将在程序体内使用的变量。尽管不建议这样做,但由于它会动态处理变量初始化,因此对于理解变量的状态
awk
会很有帮助BEGIN
echo "1,2,3" | awk 'BEGIN {FS=OFS=","; counter = 0; } $1 == "1" { counter++ }'
一般会进行什么类型的动作END
?
跟踪命令正文中处理的行数
awk
。一个通用的习惯用法是跟踪文件中的行数,我们使用特殊awk
变量NR
,它是一个运行计数器,随着每行的处理而递增。即第一行变量值将为 1,然后递增。但鉴于此,我们如何打印文件中的总行数。无法在文件正文中执行此操作,因为它会在处理文件print NR
时打印当前行号。awk
例如,下面的第一个片段将不起作用。因此,END
当其中的语句得到时,就会出现这种情况后文件处理完成。因此,以同样的方式进行打印END
,我们将打印存储在中的最后一个值NR
printf '1\n2\n\3' | awk '{print "total="NR}' total=1 total=2 total=3 printf '1\n2\n\3' | awk 'END{print "total="NR}' total=3
与
BEGIN
打印标题信息的子句一样,您可以打印字符串、信息作为摘要,因为此时所有文件处理都将完成。
本文档有效的 AWK 编程是更好地了解该工具的最佳资源。
答案2
《有效的AWK编程》对我帮助很大。
awk 适用于规则,规则由一种模式和一个操作组成,您可以省略其中任何一个,但不能同时省略两者。 BEGIN 和 END 是一个模式,{...} 是一个操作。如果没有模式或模式匹配,则将执行操作。
awk 'BEGIN {FS=OFS=","} {print $1}'
^pattern + ^action ^ action without pattern
awk '{ FS = "," } ; { print $1 }'
^action without pattern ^ another action without pattern
在常见的 awk 程序中:
- BEGIN{...} 在任何记录之前执行,您可以在这里初始化您需要的一切。
- 每条记录都会执行pattern{...},这是主循环
- END{...} 在最后一条记录之后执行。主循环已经完成,所有数据都在你手中,你可以做任何你想做的事情。