LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
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 09-16-2011, 02:50 PM   #1
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Rep: Reputation: Disabled
How would I do this...


Please look at the following:

Code:
# network.txt
config interface lan
	option ifname	eth0.1
	option type	bridge
	option proto	static
	option ipaddr	192.168.1.1
	option netmask	255.255.255.0

config interface wan
	option ifname	eth1 #<- How do I grab this, store it as a var?
	option proto	dhcp
In this case I'm trying to grab eth1. It's not aways going to be eth1.

I was trying something like:

cat network.txt | grep "something"

If I try cat network.txt | grep "option ifname"

I get

Code:
	option ifname	lo
	option ifname	eth0.1
	option ifname	eth1
However, I only wanted the line that belonged to

Code:
config interface wan
which would be

Code:
option ifname	eth1
but then that's still too much info because I wanted the last word:

Code:
eth1
Then I want to take the answer (In this case eth1) and store it as X=(the answer)

Last edited by Mouse750; 09-16-2011 at 02:54 PM.
 
Old 09-16-2011, 03:59 PM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Use awk:
Code:
awk '($1=="config" && $2=="interface") { active = ($3=="wan") }
     (active && $1=="option" && $2=="ifname") { print $3; ok=1; exit(0) }
     END { exit(1-ok) }' network.txt
When it sees the "config interface wan" line, it will set active to true.

When active is true, and it sees "option ifname", it will print the third field, set ok to 1, and exit (skip to the end rule).

At END, if ok has been set to 1, the value was printed, and the scriptlet returns exit status 0. Otherwise it will return exit status 1.

This means that in a Bourne shell, POSIX shell, or Bash script, you can use
Code:
if IFNAME=`awk '($1=="config" && $2=="interface") { active = ($3=="wan") }
                 (active && $1=="option" && $2=="ifname") { print $3; ok=1; exit(0) }
                 END { exit(1-ok) }' network.txt` ; then
        echo "WAN interface is up, $IFNAME"
else
        echo "WAN interface is down."
fi
Another possibility is to do the same thing in sed:
Code:
sed -ne '/^[\t ]*config[\t ]\+interface[\t ]\+wan[\t ]*$/,/^[\t ]*config[\t ]/ s|^[\t ]*option[\t ]\+ifname[\t ]\+\([^\t ]\+\).*$|\1|p' network.txt
although it will not return nonzero exit status when nothing is output.

Last edited by Nominal Animal; 09-16-2011 at 04:02 PM.
 
1 members found this post helpful.
Old 09-16-2011, 04:39 PM   #3
DoomUs
LQ Newbie
 
Registered: May 2011
Posts: 10

Rep: Reputation: Disabled
Another solution.

I'm assuming you're using strictly utilities available in the terminal, i.e. bash commands, is that right?

If so, do you plan on writing a script to do this or what?

When you suggest storing your result as X=(the answer) are you referring to an environment variable called X?

Will Networking.txt always be the same?

This is NOT the cleanest or best way to do this, in fact, it can likely be done with one or two "awk" or "grep" or "sed" statements, I'm just not that good, so hacking though,
Here's my suggestion, hopefully it gets you in the right direction.
Code:
head -`echo 7 + $(cat -n network.txt | grep -r "config.*wan$" | awk -F " " '{print $1}') | bc` network.txt | tail -5 | grep "option ifname" | awk -F " " '{print $3}'
the explanation:
Code:
//(1) write out the network.txt file with line numbers and print the line that has "config" and ends with "wan" because that's the interface you're looking for
cat -n network.txt | grep -r "config.*wan$"

//(2)send (1) via pipe to this statement to get just the line number from that string
awk -F " " '{print $1}'

//(3) with (2), we now just have a line-number (let's suppose it was at line 8), which we pipe to "bc" to add with 7 from the echo the simplified code looks like this
//we want to add some lines to the number eight where we found the "config.*wan$" string because the option iface will be after that
echo 7 + 8 | bc
//this echo piped to bc produces the number 15.

//(4) with the number 15, we pass as an argument to "head", which will pull the first 15 lines of a file provided
head -15 network.txt

//(5) with the first 15 lines of network.txt, we don't need all of them, we really only need the ones concerning the "wan" interface, so we pipe to tail
//so we end up with the last 5 lines of the first 15 lines of network.txt
head -15 network.txt | tail -5

//(6) we pipe this to grep for the "option iface" you were actually looking for
head -15 network.txt | tail -5 | grep "option ifname"

//(7) now we have the line we want "option ifname eth1" which we can cut up with awk to get the 3rd "element" of
head -15 network.txt | tail -5 | grep "option ifname" | awk -F " " '{print $3}'

//(8) we're all done, and it prints
eth1

//(9) set it to a variable
a=$(head -`echo 7 + $(cat -n network.txt | grep -r "config.*wan$" | awk -F " " '{print $1}') | bc` network.txt | tail -5 | grep "option ifname" | awk -F " " '{print $3}')
 
1 members found this post helpful.
Old 09-16-2011, 08:09 PM   #4
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Original Poster
Rep: Reputation: Disabled
Thank You!!!

This is the reason I was asking:

Code:
#!/bin/sh                                                                 
                                                                          
if IFNAME=`awk '($1=="config" && $2=="interface") { active = ($3=="wan") }
(active && $1=="option" && $2=="ifname") { print $3; ok=1; exit(0) }
END { exit(1-ok) }' /etc/config/network` ; then       

        iptables -R zone_wan_ACCEPT 1 -j ACCEPT -p tcp --destination-port 443 -o $IFNAME
else
        echo "iface not found in network, iptable rule not set"
fi
Your code works perfect but I forget to mention that sometimes the network.txt is formated like so:

Code:
config 'interface' 'lan'
	option 'ifname'		'eth0.1'
	option 'type'		'bridge'
	option 'proto'		'static'
	option 'ipaddr'		'192.168.1.1'
	option 'netmask'	'255.255.255.0'

config 'interface' 'wan'
	option 'ifname'		'eth1'
	option 'proto'		'dhcp'
How did you get so good at awk and sed? I'm just taking online shell tutorials but dream of getting as good as you.

Last edited by Mouse750; 09-16-2011 at 08:44 PM.
 
Old 09-16-2011, 10:12 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
A sed alternative:
Code:
sed -r '/config interface wan/,/config/{/ifname[\t ]/{s/.*ifname[\t ]+([^ ]*).*/\1/;q}};d' network.txt
Kevin Barry

Last edited by ta0kira; 09-16-2011 at 10:21 PM.
 
Old 09-16-2011, 10:47 PM   #6
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Original Poster
Rep: Reputation: Disabled
@ta0kira,

How do I use your example?
Code:
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config#
I keep running it but nothing happens?
 
Old 09-16-2011, 11:18 PM   #7
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by Mouse750 View Post
@ta0kira,

How do I use your example?
Code:
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config# sed -r '/config interface wan/,/config/{/ifname /{s/.*ifname +([^ ]+)/\1/;p}};d' network.txt
root@router:/etc/config#
I keep running it but nothing happens?
That version didn't allow for tabs, which I fixed shortly after I posted it (the tabs copied as spaces from the forum page). Please see my post again for a better version.
Kevin Barry
 
1 members found this post helpful.
Old 09-17-2011, 04:14 AM   #8
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by ta0kira View Post
That version didn't allow for tabs, which I fixed shortly after I posted it (the tabs copied as spaces from the forum page). Please see my post again for a better version.
Kevin Barry
Kevin, Would it be possible to make the code also work for:

Code:
#network.txt
config 'interface' 'lan'
	option 'ifname'		'eth0.1'
	option 'type'		'bridge'
	option 'proto'		'static'
	option 'ipaddr'		'192.168.1.1'
	option 'netmask'	'255.255.255.0'

config 'interface' 'wan'
	option 'ifname'		'eth1'
	option 'proto'		'dhcp'
Aslo, how do I store sed's output to a var?
 
Old 09-17-2011, 04:23 AM   #9
Nylex
LQ Addict
 
Registered: Jul 2003
Location: London, UK
Distribution: Slackware
Posts: 7,464

Rep: Reputation: Disabled
Quote:
Originally Posted by Mouse750 View Post
Aslo, how do I store sed's output to a var?
If you're using Bash, see this (the bottom of that page is what you want). The Advanced Bash Scripting Guide is pretty good in general.
 
1 members found this post helpful.
Old 09-17-2011, 04:34 AM   #10
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Original Poster
Rep: Reputation: Disabled
Thanks, Nylex

I was trying IFACE=$(( sed foo bar )) but after reading your link It was IFACE=$(sed foo bar)

Now if I could only get that code to also work for:
Code:
#network.txt
config 'interface' 'lan'
	option 'ifname'		'eth0.1'
	option 'type'		'bridge'
	option 'proto'		'static'
	option 'ipaddr'		'192.168.1.1'
	option 'netmask'	'255.255.255.0'

config 'interface' 'wan'
	option 'ifname'		'eth1'
	option 'proto'		'dhcp'
After this, I'm going to try my best to learn sed and awk, any tutorial links welcome.

Last edited by Mouse750; 09-17-2011 at 04:44 AM.
 
Old 09-17-2011, 07:00 AM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Well I am not sure why this needs to be so hard:
Code:
IFACE=$(awk '/wan/{getline;gsub(/\047/,"");print $NF}') network.txt

IFACE=$(sed -nr "/wan/{n;s/'//g;s/.*[[:space:]]+(.+)/\1/p}") network.txt

IFACE=$(ruby -ane "puts readline.scan(/.+[[:space:]]'?([^']+)'?/)[0] if /wan/") network.txt
 
Old 09-17-2011, 07:09 AM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by Mouse750 View Post
Kevin, Would it be possible to make the code also work for:

Code:
#network.txt
config 'interface' 'lan'
	option 'ifname'		'eth0.1'
	option 'type'		'bridge'
	option 'proto'		'static'
	option 'ipaddr'		'192.168.1.1'
	option 'netmask'	'255.255.255.0'

config 'interface' 'wan'
	option 'ifname'		'eth1'
	option 'proto'		'dhcp'
Aslo, how do I store sed's output to a var?
Code:
IFACE="$( sed -r "s/'//g;"'s/[\t ]+/ /g;/config interface wan/,/config/{/ifname /{s/.*ifname ([^ ]*).*/\1/;q}};d' network.txt )"
I also made a few changes that just clean it up a little.
Kevin Barry

Last edited by ta0kira; 09-17-2011 at 07:45 AM.
 
Old 09-17-2011, 07:14 AM   #13
Nylex
LQ Addict
 
Registered: Jul 2003
Location: London, UK
Distribution: Slackware
Posts: 7,464

Rep: Reputation: Disabled
Quote:
Originally Posted by Mouse750 View Post
After this, I'm going to try my best to learn sed and awk, any tutorial links welcome.
Have a look at http://www.grymoire.com/Unix/.
 
1 members found this post helpful.
Old 09-17-2011, 09:55 AM   #14
Mouse750
Member
 
Registered: Aug 2011
Distribution: Ubuntu
Posts: 50

Original Poster
Rep: Reputation: Disabled
Thanks You!!

TaOkira, your code works great on both. Is there any way possible you could explain your code in such a way that a complete amateur such as myself could at least understand some of it?. I try using sed for simple things but I get stuck when I run into special characters.

grail, I could not get your awk or sed code to work. I was just getting a flashing prompt. I don't know what I was doing wrong.

Last edited by Mouse750; 09-17-2011 at 12:13 PM.
 
Old 09-17-2011, 10:33 AM   #15
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Strange ... you didn't by chance change any of the quotes?
 
  


Reply



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



LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:41 PM.

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
Open Source Consulting | Domain Registration