Print out onto same line with ":" separating variables - bash

I have the following piece of code and would like to display HOST and RESULT side by side with a : separating them.
HOST=`grep pers results.txt | cut -d':' -f2 | awk '{print $1}'`
RESULT=`grep cleanup results.txt | cut -d':' -f2 | awk '{print $1}' | sed -e 's/K/000/' -'s/M/000000/'`
echo ${HOST}${RESULT}
Please can anyone assist with the final command to display these, I am just getting all of hosts and then all of results.

You probably want this:
HOST=( `grep pers results.txt | cut -d':' -f2 | awk '{ print $1 }'` ) #keep the output of the command in an array
RESULT=( `grep cleanup results.txt | cut -d':' -f2 | awk '{ print $1 }' | sed -e 's/K/000/' -'s/M/000000/'` )
for i in "${!HOST[#]}"; do
echo "${HOST[$i]}:${RESULT[$i]}"
done

A version that works without arrays, using an extra file handle to read from 2 sources at at time.
while read host; read result <&3; do
echo "$host:$result"
done < <( grep peers results.txt | cut -d: -f2 | awk '{print $1}' ) \
3< <( grep cleanup results.txt | cut -d':' -f2 | awk '{print $1}' | sed -e 's/K/000/' -'s/M/000000/')
It's still not quite POSIX, as it requires process substitution. You could instead use explicit fifes. (Also, an attempt to shorten the pipelines that produce the hosts and results. It's probably possible to combine this into a single awk command, since you can either do the substitution in awk, or pipe to sed from within awk. But this is all off-topic, so I leave it as an exercise to the reader.)
mkfifo hostsrc
mkfifo resultsrc
awk -F: '/peers/ {split($2, a, ' '); print a[1]}' results.txt > hostsrc &
awk -F: '/cleanup/ {split($2, a, ' '); print a[1]}' results.txt | sed -e 's/K/000' -e 's/M/000000/' > resultsrc &
while read host; read result <&3; do
echo "$host:$result"
done < hostsrc 3< resultsrc

Related

How to grab fields in inverted commas

I have a text file which contains the following lines:
"user","password_last_changed","expires_in"
"jeffrey","2021-09-21 12:54:26","90 days"
"root","2021-09-21 11:06:57","0 days"
How can I grab two fields jeffrey and 90 days from inverted commas and save in a variable.
If awk is an option, you could save an array and then save the elements as individual variables.
$ IFS="\"" read -ra var <<< $(awk -F, '/jeffrey/{ print $1, $NF }' input_file)
$ $ var2="${var[3]}"
$ echo "$var2"
90 days
$ var1="${var[1]}"
$ echo "$var1"
jeffrey
while read -r line; do # read in line by line
name=$(echo $line | awk -F, ' { print $1} ' | sed 's/"//g') # grap first col and strip "
expire=$(echo $line | awk -F, ' { print $3} '| sed 's/"//g') # grap third col and strip "
echo "$name" "$expire" # do your business
done < yourfile.txt
IFS=","
arr=( $(cat txt | head -2 | tail -1 | cut -d, -f 1,3 | tr -d '"') )
echo "${arr[0]}"
echo "${arr[1]}"
The result is into an array, you can access to the elements by index.
May be this below method will help you using
sed and awk command
#!/bin/sh
username=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $1}')
echo "$username"
expires_in=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $3}')
echo "$expires_in"
Output :
jeffrey
90 days
Note :
This above method will work if their is only distinct username
As far i know username are not duplicate

Print output of two commands in one line

I'm got this working:
while sleep 5s
do
lscpu | grep 'CPU MHz:' | cut -d ':' -f 2 | awk '{$1=$1};1' && grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}'
done
And it gives me the following output:
1601.058
3.4811%
1452.514
3.48059%
1993.800
3.48006%
2085.585
3.47955%
2757.776
3.47902%
1370.237
3.47851%
1497.903
3.47798%
But I'd really like to get the two values onto a single line. Every time I try to do this I run into a double / single quote variable issue. Granted I pulled some of this awk stuff from online so I'm not really up to speed on that. I just want to print per line, CPU clock and load ever 5 seconds.
Can you help me find a better way to do that?
You may use process substitution to run lscpu and cat /proc/stat and feed to single command. No need to use pipes.
while sleep 5; do
awk '/CPU MHz:/{printf "%s ", $NF} /cpu /{print ($2+$4)*100/($2+$4+$5)"%"}' <(lscpu) /proc/stat
done
If there is only one input command:
date| awk '{print $1}'
Wed
OR
awk '{print $NF}' <(date)
2019
If more then one command: Example , get the year of of the two date command in same line. (not very useful example, only for sake of demo)
awk '{printf "%s ", $1=NF}END{print ""}' <(date) <(date)
2019 2019
pipe the output of the 2 commands into paste
while sleep 5; do
lscpu | awk -F':[[:blank:]]+' '$1 == "CPU MHz" {print $2}'
awk '$1 == "cpu" {printf "%.4f%%\n", ($2+$4)*100/($2+$4+$5)}' /proc/stat
done | paste - -
The 2 columns will be separated by a tab.
Writing this for readability rather than efficiency, you might consider something like:
while sleep 5; do
cpu_pct=$(lscpu | awk -F': +' '/CPU MHz:/ { print $2 }')
usage=$(awk '/cpu / {usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' /proc/stat)
printf '%s\n' "$cpu_pct $usage"
done
Command substitutions implicitly trim trailing newlines, so if lscpu | awk has output that ends in a newline, var=$(lscpu | awk) removes it; thereafter, you can use "$var" without that newline showing up.
All you need to do is change the newline on the first line to a different separator. Something like:
lscpu | ... | tr \\n : && grep ...
You can also use echo -n $(command_with_stdout). The -n switch specifies that the new line (\n) will be omitted.
while sleep 5s; do
echo -n $( lscpu | grep 'CPU MHz:' | cut -d ':' -f 2 | awk '{$1=$1};1' )
echo -n ' **** '
echo $( grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' )
done
Or the same representation in one line:
while sleep 5s; do echo -n $( lscpu | grep 'CPU MHz:' | cut -d ':' -f 2 | awk '{$1=$1};1' ); echo -n ' **** '; echo $( grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' ); done
EDIT: (remove -n switch from echo according to Charles Duffy's comment)
while sleep 5s; do echo "$( lscpu | grep 'CPU MHz:' | cut -d ':' -f 2 | awk '{$1=$1};1' ) **** $( grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}' )"; done

what does this bash script line of code mean

I am new to shell scripting and I found following line of code in a given script.
Could someone explain me with an example what the following line of code means
Path=`echo $line | awk -F '|' '{print $1}'`
echo $line will print the value of the variable $line, the | symbol means that the output of this will be passed (or piped) to another program/command/script. I will not attempt to explain awk here, but what is done above is that the output from the echo $line is taken and processed with it.
the option -FS as per awk man page means
-F fs Use fs for the input field separator
so the string after it will be used to split the input string given to awk into different fields. Example, you variable $line has a value of a|b it will be split into two fields a and b. What is to be done with this is specified within the '{}' expression.
Again, what can be done in there is next to infinite, here the only thing that is done is to print the first field which can be accessed with $1, or a in the above example ($2 would be b as can be guessed).
Finally, the output of this whole operation is then stored in the variable Path.
to summarize:
line="a|b"
echo $line | awk -F '|' '{print $1}'
> a
Path=`echo $line | awk -F '|' '{print $1}'`
echo $Path
> a
echo $line | awk -F '|' '{print $1}'
Explanation:
echo -> display a line of text
$line -> parameter expansion read the line
| -> A pipeline is a sequence of one or more commands separated by one of the control operators |
awk -> Invoke awk program
-F '|' -> Field separator as | for the data feed
'{print $1}' -> Print the first field
Example
echo 'a|b|c' | awk -F '|' '{print $1}'
will print a
I think this is just a complicated way to express
echo ${line%%|*}
i.e. write to stdout the part of the content of the variable line which goes up to - but not including - the first vertical bar.
Path=`echo $line | awk -F '|' '{print $1}'`
^ ^ ^ ^
| | | |
| | | print 1st column
| | |
| | input field separator
| |
| echo variable line
|
variable Path
-F'|' - by default awk splits record/line/row into columns by single space, but with |, awk splits by pipe
Above one can be written as
Path=$( awk -F '|' '{ print $1 }' <<< "$line" )
Suppose say
$ line="1|2|3"
$ Path=$( awk -F '|' '{ print $1 }' <<< "$line" )
$ echo $Path; # you get first column
1
Same as
$ Path=$( cut -d'|' -f1 <<< "$line" )
$ echo $Path;
1
the default field separator is ' ', if you have -F , means change default separator to '|'

Bash Cut text from line with different delimiters

I have a variable with value like:
#capability_ids type="list">[LOADBALANCER]</capability_ids>#
And need to extract from this string type of equipment ( LOADBALANCER ).
I've tried to use cut, but don't know how write cut command with different delimiters.
DeviceType=$( echo $DeviceTypeDirty | cut -d'[' -f1)
Can enywone help me with right solution on bash?
use awk with regular expression: awk -F '[\\[\\]]' '{print $2}'
$ echo '#capability_ids type="list">[L3SWITCH]/capability_ids>#'|awk -F '[\\[\\]]' '{print $2}'
$ L3SWITCH
$ DeviceType=$( echo "$DeviceTypeDirty" | awk -F '[\\[\\]]' '{print $2}')
I tried and got to extract "LOADBALANCER"
Administrators-MacBook-Pro:~$ echo "\"list\">[LOADBALANCER]
</capability_ids>#"|awk -F '[][]' '{print $2}'
LOADBALANCER
Administrators-MacBook-Pro:~$
Hope that helps!
Using cut:
DeviceTypeDirty="#capability_ids type="list">[LOADBALANCER]</capability_ids>#"
DeviceType="$(echo "$DeviceTypeDirty" | cut -d'[' -f2 | cut -d']' -f1)"
Output:
echo "$DeviceType"
LOADBALANCER

Hide output of cat command

I have this line of code which I would like to hide its output.
Vrs=$(cat $(echo $line | awk -F"-" '{print "/var/AS-"$2"-"toupper($3)"-"$4}') | grep "YES" | cut -d":" -f5)
I have tried to include &> /dev/null at the end of the line but it doesn't work.
Does anyone know how to do this?
I am not exactly sure what you are trying to achieve, but your cat call looks redundant to me.
Vrs=$(echo "$line" | awk -F"-" '{print "/var/AS-"$2"-"toupper($3)"-"$4}' | grep "YES" | cut -d":" -f5)
You could rephrase the statement to
Vrs=$(echo "$line" | awk -F"-" '{print "/var/AS-"$2"-"toupper($3)"-"$4}' | grep "YES" | cut -d":" -f5)
This does the same thing. In the command is successful, you would get the result stored in Vrs. No output would be shown in the stdout. However, if you expect errors, you could do :
Vrs=$(echo "$line" | awk -F"-" '{print "/var/AS-"$2"-"toupper($3)"-"$4}' | grep "YES" | cut -d":" -f5 2>/dev/null)
This will suppress the errors and give you an empty $Vrs
Notes:
I have double quoted $line to prevent globbing and word splitting.

Resources