"sed/awk" value assignment in bash scripting - bash

I have a file "IP" with number of blocked different subnet IP addresses, I want to change last octal digits of subnet, like 1.1.1.5 to 1.1.1.0/24. I wrote script. Issue is that awk command out doesn't assigned to any variable.
Example:
sed "s/139.196.8.79/139.196.8.0\/24/g" ip |a=$(awk -F. '{print $4}')
But when I run awk -F. '{print S4}', it returns output but doesn't assign value to variable.
Thanks in advance.

Not sure about your expected output but... looking your example here above, maybe, you're looking for something like this:
$ a=$(sed "s/139.196.8.79/139.196.8.0\/24/g" ip | awk -F. '{print $4}')
$ echo $a
0/24

WHat you were trying to write is:
a="$(sed "s/139.196.8.79/139.196.8.0\/24/g" ip | awk -F. '{print $4}' )"
but you need to escape the RE metacharacters (.s) and you don't need sed when you're using awk:
a="$(awk -F. '{gsub(/139\.196\.8\.79/,"139.196.8.0/24"); print $4}' ip)"
The above is untested and may be wrong or not the best approach since you didn't provide any sample input and expected output in your question.
Note that the above should really be using word boundaries if an IP addr like 139.196.8.790 can occur in your data but again without sample input and expected output....

A pipe creates a sub process. This means that you create the variable in a sub shell, which gets discarded right after. In order to access the variable, you have to group your commands into curly braces:
sed "s/139.196.8.79/139.196.8.0\/24/g" ip | {
a=$(awk -F. '{print $4}')
echo $a
}
Everything you want to do with a must be done in the sub shell, in which a has been defined.

Related

How can I use a variable as input in a awk command?

I have this variable:
a='/08/OPT/imaginary/N/08_i_N.out'
I want to use "/" as a field separator.
Then, I want to extract the first pattern.
I have tried:
awk -F/ '{print $1}' "$a"
But I get:
awk: cannot open /08/OPT/imaginary/N/08_i_N.out (No such file or directory)
I do not want the file, only to work on the path of that file.
Same way as any other command, either of these (or other alternatives, e.g. within "here-documents" or passed as awk variables or...):
printf '%s\n' "$a" | command
command <<<"$a"

grep launches background processes

I have an input file that contains several path, including one referring to a initial solution. Corresponding line is the following:
initial_solution_file = ../../INIT/foo
What I would like to do is having an alias that would display this path so that I would type "init" and the shell would return " the initial solution is: ../../INIT/foo"
What I have tried is:
grep initial_solution_file input_file | awk '{print $3}' | echo "the initial solution is:" `xargs echo`
It provides the desired output, but I additionaly get something like:
[6] 48201 48202
What is this and how to prevent it from happening ?
Thanks in advance
echo "the initial solution is: $(awk '/initial_solution_file/{print $3}' input_file)"
the initial solution is: ../../INIT/foo
There is no need of pipes , you can do command substitution by using $(....) construct. Also, grep and awk can be done by awk alone.

How do i count 1 or more items in comma separated input in Shell

Here's my issue, i know how to count the files using the following two strategies but i have a problem with each one.
I am using '.sh' extension.
First:
count=`echo $2 | awk -F, {'print NF'}`
causes my program to throw an error at me: awk: cannot execute - No such file or directory
Secondly:
count=`echo $2 | tr -cd , | wc -c`
Works if you have multiple values separated by commas, however, it will not work if the input is a single item with no commas.
Like i said, this was previously working with the awk but for some reason when i ran it on the physical device instead of the virtual machine it gave me that error.
any ideas?
Thing I know are NOT the issue:
Version of shell is the same.
Try count=$(echo ${2} | awk -F, '{print NF}') instead - you have your braces and quotes inside-out.
Although, it seems your bigger problem is that awk appears to not be executable... You might try which awk and ls -l $(which awk) to see what's up with that...

How to pass a bash variable as value of awk parameter?

I would like to replace a variable inside the the awk command with a bash variable.
For example:
var="one two three"
echo $var | awk "{print $2}"
I want to replace the $2 with the var variable. I have tried awk -v as well as something like awk "{ print ${$wordnum} } to no avail.
Sightly different approach:
$ echo $var
one two three
$ field=3
$ echo $var | awk -v f="$field" '{print $f}'
three
$ field=2
$ echo $var | awk -v f="$field" '{print $f}'
two
You've almost got it...
$ myfield='$3'
$ echo $var | awk "{print $myfield}"
three
The hard quotes on the first line prevent interpretation of $3 by the shell. The soft quotes on the second line allow variable replacement.
You can concatenate parts of awk statements with variables. Maybe this is what you want in your script file:
echo $1|awk '{print($'$2');}'
Here the parts {print($ and the value of local variable $2 and );} are concatenated and given to awk.
EDIT: After some advice rather don't use this. Maybe as a one-time solution. It's better to get accustomed to doing it right right away - see link in first comment.

Substring extraction using bash shell scripting and awk

So, I have a file called 'dummy' which contains the string:
"There is 100% packet loss at node 1".
I also have a small script that I want to use to grab the percentage from this file. The script is below.
result=`grep 'packet loss' dummy` |
awk '{ first=match($0,"[0-9]+%")
last=match($0," packet loss")
s=substr($0,first,last-first)
print s}'
echo $result
I want the value of $result to basically be 100% in this case. But for some reason, it just prints out a blank string. Can anyone help me?
You would need to put the closing backtick after the end of the awk command, but it's preferable to use $() instead:
result=$( grep 'packet loss' dummy |
awk '{ first=match($0,"[0-9]+%")
last=match($0," packet loss")
s=substr($0,first,last-first)
print s}' )
echo $result
but you could just do:
result=$( grep 'packet loss' | grep -o "[0-9]\+%" )
Try
awk '{print $3}'
instead.
the solution below can be used when you don't know where the percentage numbers are( and there's no need to use awk with greps)
$ results=$(awk '/packet loss/{for(i=1;i<=NF;i++)if($i~/[0-9]+%$/)print $i}' file)
$ echo $results
100%
You could do this with bash alone using expr.
i=`expr "There is 98.76% packet loss at node 1" : '[^0-9.]*\([0-9.]*%\)[^0-9.]*'`; echo $i;
This extracts the substring matching the regex within \( \).
Here I'm assuming that the output lines you're interested in adhere strictly to your example, with the percentage value being the only variation.
With that assumption, you really don't need anything more complicated than:
awk '/packet loss/ { print $3 }' dummy
This quite literally means "print the 3rd field of any lines containing 'packet loss' in them". By default awk treats whitespace as field delimiters, which is perfect for you.
If you are doing more than simply printing the percentage, you could save the results to a shell variable using backticks, or redirect the output to a file. But your sample code simply echoes the percentages to stdout, and then exits. The one-liner does the exact same thing. No need for backticks or $() or any other shell machinations whatsoever.
NB: In my experience, piping the output of grep to awk is usually doing something that awk can do all by itself.

Resources