LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-29-2012, 06:58 PM   #1
theillien
Member
 
Registered: Jan 2004
Posts: 107

Rep: Reputation: 1
Using script variable in awk subtraction


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.
Attached Images
File Type: png fix_eth.PNG (29.7 KB, 2 views)

Last edited by theillien; 05-29-2012 at 07:04 PM. Reason: The MAC[$i] assignment was missing. This has no affect on the rest of the script during debugging, though.
 
Old 05-29-2012, 07:22 PM   #2
theillien
Member
 
Registered: Jan 2004
Posts: 107

Original Poster
Rep: Reputation: 1
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.
 
Old 05-30-2012, 04:42 AM   #3
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,689

Rep: Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987
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 ))
 
Old 05-30-2012, 04:55 AM   #4
pan64
Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 5,142

Rep: Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364
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
 
Old 05-30-2012, 09:24 AM   #5
theillien
Member
 
Registered: Jan 2004
Posts: 107

Original Poster
Rep: Reputation: 1
What would the one awk in the MAC line look like?
 
Old 05-30-2012, 09:31 AM   #6
pan64
Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 5,142

Rep: Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364
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")
 
Old 05-30-2012, 10:15 AM   #7
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,689

Rep: Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987Reputation: 1987
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 ))
 
Old 06-11-2012, 10:25 AM   #8
theillien
Member
 
Registered: Jan 2004
Posts: 107

Original Poster
Rep: Reputation: 1
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] shell script -- awk variable substitution r2d2#jedi Linux - General 2 10-07-2010 10:04 PM
Shell variable in awk script rohini_sharma Programming 3 02-22-2010 09:32 AM
Run AWK script on contents of a variable EmrldDrgn Linux - Newbie 3 07-10-2009 06:05 AM
Using global variable in awk (bash script) kopeda Programming 2 04-24-2007 02:47 AM
Accessing Shell variable in awk script dileepkk Linux - General 1 10-07-2004 08:47 AM


All times are GMT -5. The time now is 01:36 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration