101. getline 命令
如您所知,awk 脚本的主体块对输入文件中的每一行执行一次。您无法对其进行任何控制,因为 awk 会自动进行控制。
但是,使用 getline
命令,您可以控制从输入文件(或其他文件)中读取行。
请注意,执行 getline
后,awk 脚本会相应地设置
NF
、
NR
、
FNR
和
$0
内置变量的值。
简单的 getline
$ awk -F"," '{getline; print $0;}' items.txt 102,Refrigerator,Appliance,850,2 104,Tennis Racket,Sports,190,20 105,Laser Printer,Office,475,5
当您仅在主体块中指定 getline
时,awk 会从输入文件中读取下一行。
在此示例中,bod 块中的第一个语句是 getline
。 因此,即使 awk 已经从输入文件中读取了第一行, getline
也会读取下一行,因为我们明确地从输入文件中请求下一行。
因此,在 getline
之后执行 'print $0'
会使 awk 打印第二行。
下面是它的工作原理:
- 在主体块的开头,在执行任何语句之前,awk 读取 「items.txt」 的第一行并将其存储在
$0
中 getline
- 我们强制 awk 从输入文件中读取下一行并将其存储在内置的$0
变量中。print $0
- 由于第 2 行被读入$0
,因此print $0
将打印第 2 行(而不是第 1 行)。- 主体块以相同的方式继续处理 「items.txt」 中的其余行,并且仅打印偶数行。
getline
到变量
您还可以将输入文件中的下一行获取到变量中(而不是将其读取到
$0
)。
以下示例仅打印奇数行。
$ awk -F"," '{getline tmp; print $0;}' items.txt
101,HD Camcorder,Video,210,10
103,MP3 Player,Audio,270,15
105,Laser Printer,Office,475,5
下面是它的工作原理:
- 在主体块的开头,在执行任何语句之前,awk 读取 「items.txt」 的第一行并将其存储在
$0
中 getline tmp
- 我们强制 awk 从输入文件中读取下一行并将其存储在tmp
变量中。print $0
-$0
仍然包含第一行,因为"getline tmp"
没有覆盖$0
的值。因此,print $0
将打印第一行(而不是第二行)。- 主体块以相同的方式继续处理 「items.txt」 中的其余行,并且仅打印奇数行。
以下示例同时打印
$0
和
tmp
。 如下所示,
$0
包含奇数行,
tmp
包含偶数行。
$ awk -F"," '{getline tmp; print "$0->", $0; print "tmp->", tmp;}' items.txt
$0-> 101,HD Camcorder,Video,210,10
tmp-> 102,Refrigerator,Appliance,850,2
$0-> 103,MP3 Player,Audio,270,15
tmp-> 104,Tennis Racket,Sports,190,20
$0-> 105,Laser Printer,Office,475,5
tmp-> 104,Tennis Racket,Sports,190,20
getline
从不同的文件获取
前面的两个示例从给定的输入文件本身读取该行。使用 getline
您还可以从不同的文件(与当前输入文件)读取行,如下所示。
在两个文件之间来回切换,打印每个文件中的行。
$ awk -F"," '{print $0; getline < "items-sold.txt"; print $0;}' items.txt
101,HD Camcorder,Video,210,10
101 2 10 5 8 10 12
102,Refrigerator,Appliance,850,2
102 0 1 4 3 0 2
103,MP3 Player,Audio,270,15
103 10 6 11 20 5 13
104,Tennis Racket,Sports,190,20
104 2 3 4 0 6 5
105,Laser Printer,Office,475,5
105 10 2 5 7 12 6
下面是它的工作原理:
- 在主体块的开头,在执行任何语句之前,awk 读取 「items.txt」 的第一行并将其存储在
$0
中 print $0
- 打印 「items.txt」 中的第一行getline < "items-sold.txt"
- 从 「itemssold.txt」 读取第一行并将其存储在$0
中。print $0
- 打印 「items-sold.txt」 中的第一行(不是 「items.txt」 中的)- 正文块以相同的方式继续 「items.txt」 和 「items-sold.txt」 中的其余行
getline
从不同的文件到变量
您还可以使用 "getline var"
格式将不同文件中的行读入变量,而不是将这两个文件读入
$0
。
在两个文件之间来回切换,打印每个文件中的行(使用
tmp
变量)。
$ awk -F"," '{print $0; getline tmp < "items-sold.txt";print tmp;}' items.txt
101,HD Camcorder,Video,210,10
101 2 10 5 8 10 12
102,Refrigerator,Appliance,850,2
102 0 1 4 3 0 2
103,MP3 Player,Audio,270,15
103 10 6 11 20 5 13
104,Tennis Racket,Sports,190,20
104 2 3 4 0 6 5
105,Laser Printer,Office,475,5
105 10 2 5 7 12 6
这与前面的示例相同,只是它将第二个文件中的行存储在变量
tmp
中。
getline
执行外部命令
您还可以使用 getline
执行 UNIX 命令并获取其输出。
以下示例获取 date
命令的输出并打印它。
请注意,您还应该关闭刚刚执行的命令,如下所示。date
命令的输出存储在
$0
变量中。
使用此方法可以在报告的页眉或页脚上打印时间戳。
$ cat getline1.awk
BEGIN {
FS=",";
"date" | getline
close("date")
print "Timestamp:" $0
}
{
if ( $5 <= 5 )
print "Buy More: Order", $2, "immediately!"
else
print "Sell More: Give discount on", $2, "immediately!"
}
$ awk -f getline1.awk items.txt
Timestamp:Sat Mar 5 09:29:22 PST 2011
Sell More: Give discount on HD Camcorder immediately!
Buy More: Order Refrigerator immediately!
Sell More: Give discount on MP3 Player immediately!
Sell More: Give discount on Tennis Racket immediately!
Buy More: Order Laser Printer immediately!
您还可以将输出存储在任何 awk 变量(例如:
timestamp
)中,而不是将输出存储在
$0
变量中,如下所示。
$ cat getline2.awk
BEGIN {
FS=",";
"date" | getline timestamp
close("date")
print "Timestamp:" timestamp
}
{
if ( $5 <= 5 )
print "Buy More: Order", $2, "immediately!"
else
print "Sell More: Give discount on", $2, "immediately!"
}
$ awk -f getline2.awk items.txt
Timestamp:Sat Mar 5 09:38:22 PST 2011
Sell More: Give discount on HD Camcorder immediately!
Buy More: Order Refrigerator immediately!
Sell More: Give discount on MP3 Player immediately!
Sell More: Give discount on Tennis Racket immediately!
Buy More: Order Laser Printer immediately!