将awk命令转为awk脚本(多个F)

将awk命令转为awk脚本(多个F)

我有一个工作命令

awk  -F '[)#/(:]' 'BEGIN  { fw="";dev=""} {if ($0~/sh failover/) fw=$1 ; if (($0~/This host/)||($0~/Other host/)) dev=$2; if ($0~/\)\:/) {print $2,$1,fw, dev} }' OFS="|" test_data

我想把它变成一个脚本。当这样做时...

#!/bin/sh
awk '
BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} 
{
    if ($0~/sh failover/) fw=$1 ; 
    if (($0~/This host/)||($0~/Other host/)) dev=$2; 
    if ($0~/\)\:/) {
        print $2,$1,fw, dev
        } 
}' test_data 

...F='[)#/(:]' 会导致错误。

[...srv01]$ ./test
./test: line 3: syntax error near unexpected token `)'
./test: line 3: `BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} '
[...srv01]$ 

更改为双引号时,它将 twp 双引号之间的所有内容作为分隔符,因此将查找 )#/(: 而不是或者#或者/或者或者:

这是test_data的文件内容

[...srv01]$ cat test_data
JoeASA# sh failover | i \)\:|host
        This host: Primary - Active
                  admin Interface management (313.13.0.13): Normal (Monitored)
                  DMZ-FW Interface Inside (310.13.19.7): Normal (Not-Monitored)
                  DMZ-FW Interface Outside-Zone2 (912.168.119.7): Normal (Not-Monitored)
                  ENET Interface OUTSIDE(912.168.191.7): Normal (Not-Monitored)
                  ENET Interface dmarc (912.168.192.7): Normal (Not-Monitored)
                  GW Interface Extranet (912.168.23.27): Normal (Not-Monitored)
                  GW Interface Outside-Zone (912.168.123.27): Normal (Not-Monitored)
                  GW Interface management (331.1.1.47): Normal (Not-Monitored)
        Other host: Secondary - Standby Ready
                  admin Interface management (313.13.0.12): Normal (Monitored)
                  DMZ-FW Interface Inside (310.13.19.6): Normal (Not-Monitored)
                  DMZ-FW Interface Outside-Zone2 (912.168.119.6): Normal (Not-Monitored)
                  ENET Interface OUTSIDE(912.168.191.6): Normal (Not-Monitored)
                  ENET Interface dmarc (912.168.192.6): Normal (Not-Monitored)
                  GW Interface Extranet (912.168.23.26): Normal (Not-Monitored)
                  GW Interface Outside-Zone (912.168.123.26): Normal (Not-Monitored)
                  GW Interface management (331.1.1.46): Normal (Not-Monitored)          
SIMPLEASA1/sec/act#  sh failover | i \)\:|host
        This host: Secondary - Active
                  Interface Edge (912.168.22.17): Normal (Monitored)
                  Interface Inside (310.13.19.17): Normal (Monitored)
                  Interface EXT (912.168.50.17): Normal (Monitored)
                  Interface WIFI (912.168.11.17): Normal (Monitored)
        Other host: Primary - Standby Ready
                  Interface Edge (912.168.22.16): Normal (Monitored)
                  Interface Inside (310.13.19.16): Normal (Monitored)
                  Interface EXT (912.168.50.16): Normal (Monitored)
                  Interface WIFI (912.168.11.16): Normal (Monitored)                      
[..srv01]$ 

答案1

您将脚本作为单引号字符串从 shell 传递给 awk,但您似乎有单引号里面剧本也是如此。他们实际上结束了引用的字符串:

awk 'BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} 
                ^^^^^^^ not quoted

shell 看到一个不带引号的),这会导致语法错误。无论如何,您不想在 awk 脚本中使用单引号,它们将是语法错误在 awk 中。因此,请使用双引号,就像您对其他赋值所做的那样,它们很好地适合 shell 中的单引号,并且实际上可以在 awk 代码中工作:

awk 'BEGIN { foo="bar"; ...}'

然后,请注意-Fawk 的选项的作用是设置字段分隔符,它是变量FS,而不是F。因此,您想要拥有BEGIN { FS="[)#/(:]"; ...,并且您可能也不想更改默认的记录分隔符RS- 至少您没有在上面的一行中更改它。


另外,您可以跳过 shell,直接使 awk 成为该脚本的解释器(假设您的 awk 位于/usr/bin/awk),而不是将 awk 脚本放入 shell 脚本中:

#!/usr/bin/awk -f
BEGIN { FS="[)#/(:]"; OFS="|"; fw=""; dev=""} 
{
    if ( $0 ~ /sh failover/ ) fw=$1 ; 
    if (($0 ~ /This host/) || ($0 ~ /Other host/)) dev=$2; 
    if ( $0 ~ /\)\:/ ) {
        print $2, $1, fw, dev
    } 
}

如果它被调用./script.awk并可执行,那么您可以将其运行为./script.awk filename,即使用要处理的文件作为脚本的参数。

相关内容