Shell 将变量输入到awk脚本

Shell 将变量输入到awk脚本,shell,awk,Shell,Awk,我正在编写一个脚本,用于检测网卡上的CDP信息。该脚本目前在我的计算机上运行,但我希望其他人也能使用它。脚本当前正在运行,因为在代码中它有我的网卡的名称。在运行脚本之前,我想让它询问网卡名称,或者列出可用的网卡名称。我的代码是: #!/usr/bin/awk -f function red(s) { printf "\033[1;31m" s "\033[0m " } function green(s) { printf "\033[1;32m" s "\033[0m "

我正在编写一个脚本,用于检测网卡上的CDP信息。该脚本目前在我的计算机上运行,但我希望其他人也能使用它。脚本当前正在运行,因为在代码中它有我的网卡的名称。在运行脚本之前,我想让它询问网卡名称,或者列出可用的网卡名称。我的代码是:

#!/usr/bin/awk -f

function red(s) {
    printf "\033[1;31m" s "\033[0m "
}

function green(s) {
     printf "\033[1;32m" s "\033[0m "
}

function blue(s) {
    printf "\033[1;34m" s "\033[0m "
}

BEGIN{

cmd = "tcpdump -nvi enp0s25 -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1"
while ((cmd | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")

for(i=1;i<=length(s);i++){
    if ($0 ~ s[i] && s[i]){

            if (i==1){            
            print "\n"; 
            print red("Device Name: ") green($7);
            }   

            else if (i==2){                          
            print red("Software Version: ") green($0) ;
                }

            else if (i==3){                      /*Port*/
            print red($1 ": ") green($7);
                }
        else if (i==4){                             
            print red($1 " " $2 " " $3 ": ") green($9);
                }

            else if (i==5){                             
            print red("IP Address: ") green($9);
                }

        else if (i==6){                                 
            print red("VLAN: ") green($9);
                }

        else if (i==7){                                
            print red("DUPLEX: ") green($7);
                }

            else if (i==8){                                 
            print red("Voice VLAN: ") green($13);
                }

        else{ 
                s[i]=0;print "   "}
                }  
            }
        }
}       

如您所见,它使用我的NIC enp0s25运行命令。我需要把它变成一个变量,用户可能只输入一次。最好的方法是列举卡片,让用户使用数字选择他想要的卡片。我不知道如何做到这一点。

您试图将awk作为shell使用,将对tcpdump的调用编码到awk中,这让您的生活更加艰难。考虑一下——您正在编写一个shell脚本来调用awk来调用shell来调用tcpdump,而不是让shell调用tcpdump并将输出通过管道传输到awk

#!/usr/bin/awk -f 

function red(s) {
printf "\033[1;31m" s "\033[0m "
 }

function green(s) {
printf "\033[1;32m" s "\033[0m "
}

function blue(s) {
  printf "\033[1;34m" s "\033[0m "
 }

 function detectNic( ) {
    printf "Enter the Ethernet card to listen or press enter to listen 
         to Default:";getline nic<"/dev/tty"
      if (nic == ""){

        command = "cat /var/defaultnic"

        nic = command | getline
    print "Default network card to listen: " $nic       
    return $nic

        }
    else{   
    return nic
    }

 }
BEGIN{

nic = detectNic();
cmd = "tcpdump -nv -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1 -i"

while ((cmd nic | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")

for(i=1;i<=length(s);i++){
    if ($0 ~ s[i] && s[i]){

    #DEVICE ID
            if (i==1){            
            print "\n"; 
            print red("Device Name: ") green($7);
            }   

#SOFTWARE VERSION      
            else if (i==2){                          
            print red("Software Version: ") green($0) ;
                }

 #PORT      
            else if (i==3){                      
            print red($1 ": ") green($7);
                }
     #VTP DOMAIN    
        else if (i==4){                             
            print red($1 " " $2 " " $3 ": ") green($9);
                }

     #IP ADDRESS
            else if (i==5){                             
            print red("IP Address: ") green($9);
                }

    #CURRENT VLAN     
        else if (i==6){                                 
            print red("VLAN: ") green($9);
                }

       #DUPLEX
        else if (i==7){                                
            print red("DUPLEX: ") green($7);
                }

      #VOICE VLAN
            else if (i==8){                                 
            print red("Voice VLAN: ") green($13);
                }

        else{ 
                s[i]=0;print "   "}
                }  
            }
        }
}       
只需将shell脚本编写为:

tcpdump ... enp0s25 ... | awk 'script'
然后你可以用显而易见的方式来调整它:

echo "enter a nic: "
IFS= read -r nic
tcpdump ... "$nic" ... | awk 'script'

为什么要绕过awks的正常操作模式,例如tcpdump args | awk“script”,而硬编码getline循环?稍后我将回到您的实际问题,但您使用的printf是错误的:如果字符串包含%序列,您将得到一个错误。您需要将参数保留在格式字符串之外。我将执行函数着色,n{printf\033[1;%dm%s\033[0m,n,s},然后执行函数reds{colorizes,31},etcnic=command | getline;return$nic将nic设置为结果状态,即不是getline调用检测到的值-1、0或1,然后返回位于该位置的字段或记录$-1、0或$1。可能不是您试图执行的操作。并将文件传送到管道到getline,而不是像以前那样使用getline读取文件几行之前的getline nic