Combine multiple awk output to print on one line

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-15 03:27:06

问题


I have two different functions I wrote, each with their own AWK to search for a specific file in multiple directories and output the information I need. Both functions print the FILENAME and a specific field I need and work just fine on their own. I want to combine them together for more robust output.

I am not a programmer. I wrote these while reading about awk as I went.

Function 1

cver () {
X=""
case $1 in
("-b") X="bb";;
("-c") X="cpe";;
("-e") X="etech";;
("-k") X="core";;
("-o") X="ohgov";;
("-h"|help) echo "'cver' allows us to see the software version 
running on all Company Juniper devices.\n'cver' is especially helpful 
in determining which devices require a software upgrade.\n\nOptions 
are -b for bb, -c for cpe, -e for etech, -k for core, and -o for 
ohgov.\n\nUse grep to find specific information. Ex: cver -c | grep 
name";;
(*) echo "Unrecognized or incomplete command.\nUse -h for help.";;
  esac
[ $X ] && awk -vSRCH="$3" '/JUNOS/ && /boot/ && $5 ~ "^[[]" SRCH  
{sub ("/show.version", "", FILENAME); sub (".*/", "", FILENAME); 
print $5 " " FILENAME}' ~/svn/nw_config_data/*${X}.domain.net/show.version | sort
}

Input/Output Example:

% cver -k   <---input
[11.4R10.3] device.core.domain.net <---ouput

Function 2

cmod () {
X=""
case $1 in
("-b") X="bb";;
("-c") X="cpe";;
("-e") X="etech";;
("-k") X="core";;
("-o") X="ohgov";;
esac
awk '/Model/ {sub ("/show.version", "", FILENAME);
sub (".*/", "", FILENAME); print FILENAME " " $2}' 
~/svn/nw_config_data/*${X}.domain.net/show.version | sort
}

Input/Output Example:

% cmod -k <---input
device.core.domain.net mx480 <---output

What these scripts are doing is going into our ~/svn/nw_config_data/ directory and stored there is a directory for every device we have deployed. Within each device directory, there are files for the config, as well as some show commands. The file I'm worried about is the show.version file and a couple lines of information. For "cver" I want the JUNOS Base OS boot information. For "cmod" I want the information for Model. The "X" will then grab different device options like -b="bb" (device.bb.domain.net)

Below is an example of the show.version file.

Hostname: device-r0
Model: ex3300-24t
JUNOS Base OS boot [12.3R7.7]
JUNOS Base OS Software Suite [12.3R7.7]
JUNOS Kernel Software Suite [12.3R7.7]
JUNOS Crypto Software Suite [12.3R7.7]
JUNOS Online Documentation [12.3R7.7]
JUNOS Enterprise Software Suite [12.3R7.7]
JUNOS Packet Forwarding Engine Enterprise Software Suite [12.3R7.7]
JUNOS Routing Software Suite [12.3R7.7]
JUNOS Web Management [12.3R7.7]
JUNOS FIPS mode utilities [12.3R7.7]

I tried searching these last couple days for any kind of examples that would be similar and came up short. I saw one answer that said pipe the awk, but it only prints the second awk info.

I then tried && the awk instead of piping it, and it got me closer, but prints the first awk then the second awk on separate lines and I want them combined.

&& example:

cver () {
X=""
case $1 in
("-b") X="bb";;
("-c") X="cpe";;
("-e") X="etech";;
("-k") X="core";;
("-o") X="ohgov";;
("-h"|help) echo "'cver' allows us to see the software version 
running on all Company Juniper devices.\n'cver' is especially helpful 
in determining which devices require a software upgrade.\n\nOptions 
are -b for bb, -c for cpe, -e for etech, -k for core, and -o for 
ohgov.\n\nUse grep to find specific information. Ex: cver -c | grep 
name";;
(*) echo "Unrecognized or incomplete command.\nUse -h for help.";;
  esac
[ $X ] && awk -vSRCH="$3" '/JUNOS/ && /boot/ && $5 ~ "^[[]" SRCH 
{sub ("/show.version", "", FILENAME); sub (".*/", "", FILENAME); 
print $5 " " FILENAME}' ~/svn/nw_config_data/*${X}.domain.net/show.version 
| sort && awk '/Model/ {sub ("/show.version", "", FILENAME); 
sub (".*/", "", FILENAME); print $2}' 
~/svn/nw_config_data/*${X}.domain.net/show.version | sort

Input/Output example:

% cver -k <---input
[11.4R10.3] device.core.domain.net <---output
mx480 <---output

I want the input/output to be:

% cver -k <---input
device.core.domain.net mx480 [11.4R10.3] <---output

Which I imagine the print part of the command to look like

print FILENAME " " $2 " " $5

I've also tried adding /Model/ && $2 to my first function, but it doesn't give me any output and I'm just lost at this point.

Example:

cver () {
X=""
case $1 in
("-b") X="bb";;
("-c") X="cpe";;
("-e") X="etech";;
("-k") X="core";;
("-o") X="ohgov";;
("-h"|help) echo "'cver' allows us to see the software version 
running on all Company Juniper devices.\n'cver' is especially helpful 
in determining which devices require a software upgrade.\n\nOptions 
are -b for bb, -c for cpe, -e for etech, -k for core, and -o for 
ohgov.\n\nUse grep to find specific information. Ex: cver -c | grep 
name";;
(*) echo "Unrecognized or incomplete command.\nUse -h for help.";;
  esac
[ $X ] && awk -vSRCH="$3" '/JUNOS/ && /boot/ && $5 && /Model/ && $2 ~ "^[[]" SRCH  
{sub ("/show.version", "", FILENAME); sub (".*/", "", FILENAME); 
print FILENAME " " $2 " " $5}' ~/svn/nw_config_data/*${X}.domain.net/show.version | sort

回答1:


Your awk code is very complicated; I've shortened it considerably here into what is hopefully easier for you (and others) to understand!

The /PATTERN/{STATEMENT} lines evaluate EXPRESSION when PATTERN is matched. So it's a very simple thing to assign to a variable using that criteria. Then in the END block we print the information we've collected (rather than messing with the filename, just pass the desired info directly using the -v flag to set a variable.)

#!/bin/zsh

cver () {
    svn="$HOME/svn/nw_config_data"
    case "$1" in
        ("-b")
            host="bb.domain.net"
            ;;
        ("-c")
            host="cpe.domain.net"
            ;;
        ("-e")
            host="etech.domain.net"
            ;;
        ("-k")
            host="core.domain.net"
            ;;
        ("-o")
            host="ohgov.domain.net"
            ;;
        ("-h"|help)
            echo "'cver' allows us to see the software version running on all Company Juniper devices.\n'cver' is especially helpful in determining which devices require a software upgrade.\n\nOptions are -b for bb, -c for cpe, -e for etech, -k for core, and -o for ohgov.\n\nUse grep to find specific information. Ex: cver -c | grep name\n"
            exit 0
            ;;
        (*)
            echo "Unrecognized or incomplete command.\nUse -h for help.\n"
            exit 2
            ;;
    esac
    awk -v "h=$host" '/^JUNOS Base OS boot/{v=$5} /^Model/{m=$2} END{printf("%s %s %s\n",h,m,v)}' "$svn/$host/show.version"
}



回答2:


I just happened to mention this script to a co-worker and found out he has some programming experience. He decided to take a stab at what miken32 provided and came up with a working script that does exactly what I was looking for.

Now, we're planning on expanding this script in the near future to pull more information, accurately, since Juniper doesn't standardized their show.version information across software versions, as well as pulling the information we need from the few Cisco devices we have deployed in the field since this script is Juniper based.

We added a "-a" option to pull ALL hosts. The dirs section allows us to see all hosts for whichever option is chosen (-b,-c,-e, etc), and pops it in a for loop to prevent duplicate information from populating. I'll be adding back the help and (*) options from the old cver later.

The purpose of my original cver script was just to pull software versions of all our devices so we could start planning maintenance windows to upgrade the Juniper Software. Then I decided it would be nice to see the model too, so I wrote the cmod script to get the model. We needed that information because some models have a bug in the software upgrade process (mx80) that requires a pre-emptive reboot before loading the software.

This script is great for anyone working at an ISP or even an enterprise environment with lots of routers and switches deployed. Now you can quickly pull the information on these devices without having to login to each one and manually running commands to get this information.

And now, the new and improved cver!

#!/usr/local/bin/zsh
svn="$HOME/svn/nw_config_data/"
 case "$1" in
   ("-a")
   hosts=""
   ;;
   ("-b")
   hosts=".bb.domain.net"
   ;;
   ("-c")
   hosts=".cpe.domain.net"
   ;;
   ("-e")
   hosts=".etech.domain.net"
   ;;
   ("-k")
   hosts=".core.domain.net"
   ;;
   ("-o")
   hosts=".ohgov.domain.net"
   ;;
 esac

dirs=($(ls -d $svn*$hosts*))
for hostdir in $dirs
do
host=$(echo $hostdir | grep -Eo "(\w|\.|-)*$")

awk -v h=$host '/^JUNOS Base OS boot/{v=$5} /^Junos:/{v="["$2"]"} /^Model/{m=$2} END{if(m!="number"){printf("%s %s %s\n",h,m,v)}}' "$hostdir/show.version"
done


来源:https://stackoverflow.com/questions/47049207/combine-multiple-awk-output-to-print-on-one-line

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!