问题
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