LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Using script variable in awk subtraction (https://www.linuxquestions.org/questions/programming-9/using-script-variable-in-awk-subtraction-947470/)

theillien 05-29-2012 06:58 PM

Using script variable in awk subtraction
 
1 Attachment(s)
I have the following script:
Code:

#!/bin/bash

##################################################################
#
# Purpose:
# When RHEL6 VMs are moved between compute pools or VLANs their
# MAC addresses change breaking the interfaces. This script
# updates the ifcfg-eth* and network interface udev rules files
# to make the configuration match the new addresses.
#
# Changelog:
# 1.0 - Initial script - 05/26/2012 - msnyder
# 1.1 - Switched $udevpath to $udevfile incorporating the actual
#      file in the variable since it is always the same; added
#      documentation - 05/27/2012 - msnyder
# 2.0 - Rewrite to account for variable number of improper
#      udev file entries - 05/29/2012 - msnyder
#
##################################################################


#Set paths to file locations
udevfile=/etc/udev/rules.d/70-persistent-net.rules
netpath=/etc/sysconfig/network-scripts
ifaces=$(grep eth $udevfile |wc -l)
       
shft=$(($ifaces - 1))
adj=$(($ifaces - 3))

for (($i=0; $i<=$shft; $i++))
do
        #Extract MAC addresses of old and new udev entries
        #These will be used to update the ifcfg-eth* files
        MAC[$i]=$(grep eth$i $udevfile |awk -F ',' '{print $4}' |awk -F "==" '{print $2}')

        if [ $i -lt 3 ]
        then
                #If $i is less than 3 comment out the eth$i entry in the udev rules file
                sed -i "/eth$i/ s/^/#/" $udevfile
        elif [ $i -ge 3 ] && [ $i -lt $adj ]
        then
                #Delete the lines associated with the old "new" interfaces
                sed -i "/eth$i/d"
        else
                #Adjust the eth field to the correct value
                int=$(echo $i |awk -v val=$adj '{print ($1 - $val)}')
                sed -i "s/eth$i/eth$int/" $udevfile

                #Change the MAC address in the ifcfg-eth* files to match
                #the entry in the udev rules file for the new interfaces
                sed -i "s/HWADDR.*/HWADDR=${MAC[$i]}/" $netpath/ifcfg-eth$int
        fi
done

reboot

The issue is specifically with the line that assigns the output of the awk subtraction to the int variable:
Code:

int=$(echo $i |awk -v val=$adj '{print ($1 - $val)}')
I know that $val is being assigned the value of $adj as is evidenced by the screenshot.* However, the subtraction does not execute and the value of $int is not set properly (for an $adj of 5 I expect an $int of 2).

What am I doing wrong with this line that it isn't subtracting the value properly?

*I had to use a screenshot because the VMware console window doesn't support copying/pasting text.

theillien 05-29-2012 07:22 PM

I think I solved this. Instead of using the '-v val=$adj' assignment I used
Code:

int=$(echo $i |awk '{print ($1 - '$adj')}')
I'm now seeing the results I expect.

grail 05-30-2012 04:42 AM

Firstly, your issue was the you used $adj in awk where you call variables with their name, ie. just 'adj'.

Secondly, you previously use bash math:
Code:

adj=$(($ifaces - 3))
Is there a reason to not use it here?

Also you can simplify your current usage further:
Code:

(( adj = ifaces - 3 ))

pan64 05-30-2012 04:55 AM

the problem with that awk is that you do not need $ inside the script:
int=$(echo $i |awk -v val=$adj '{print ($1 - $val)}')
you need to remove it - but of course, (( int = i - adj )) is much better


in line: MAC[$i]=$(grep eth$i $udevfile |awk -F ',' '{print $4}' |awk -F "==" '{print $2}')
only one awk would be enough instead of grep|awk|awk

theillien 05-30-2012 09:24 AM

What would the one awk in the MAC line look like?

pan64 05-30-2012 09:31 AM

awk -F, " /eth$i/ "' { split ($4, a, "=="); print a[2] }'
I have not tested because I have no input file, but probably works, after testing:
MAC[$i]=$( this is the awk )
if you give a sample file we can try to test it also




_____________________________________
If someone helps you, or you approve of what's posted, click the "Add to Reputation" button, on the left of the post.
Happy with solution ... mark as SOLVED
(located in the "thread tools")

grail 05-30-2012 10:15 AM

I would also point out that your for loop is not going to work either as you are trying to assign the value 0 to the value of 'i' by using $i.

Also, you asked previously how to get the MAC values in your question here, which showed you a number of better methods.
Code:

ifaces=$(grep eth $udevfile |wc -l)
wc is an over kill here, try looking up the -c option for grep.

As with the math examples above you could also change your tests from the older [] form to also use (()):
Code:

if [ $i -lt 3 ]

if (( i < 3 ))


theillien 06-11-2012 10:25 AM

Thanks for the additional input. I discovered the assignment of 0 to $i when I started putting this into full test mode.

Thanks for the heads up with the -c option for grep. That should provide some more elegant lines in the future.


All times are GMT -5. The time now is 08:40 PM.