LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
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 01-16-2012, 01:32 AM   #1
contra04
LQ Newbie
 
Registered: Sep 2011
Location: London UK
Distribution: centos_fedora_DEbian
Posts: 17

Rep: Reputation: Disabled
advice required to do a replace task based on input criteria


Centos.
I have a load of config files - cisco configs actually. I need to change the interface names per device. There are 30 configs for each device, however the changes I need to make are the same despite the differences in the configs. I though Ill try and get soem help scripting this !

So if I have R1, R2... etc I need to perform some replace text on a number of lines based on a set of rules that I define. I am not sure wether to use a script that has a load of sed and case statements? - not sure how to do case in bash, or should I try to learn perl for this task?

E.g for an input file named R1 do this:

case: input filename = R1
S1/0/1 replace with S1/0
FastEthernet 0/0 replace with Ethernet 0/0

case: input filename = R2
S1/0/1 replace with S1/2
GigabitEthernet 0/0 replace with Ethernet 0/0

etc..

Last edited by contra04; 01-16-2012 at 01:33 AM.
 
Old 01-16-2012, 03:27 AM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Perhaps something like this in Bash:
Code:
for OUT in R[1-9]* ; do
    IN="$OUT.old"

    # Rename old file, keeping it as a backup (and input!)
    mv -f "$OUT" "$IN" || exit $?

    # Index is the file name, without starting R
    INDEX="${OUT#R}"

    # List of sed patterns (arguments) to apply.
    regex=()

    # Change S1/0/1 to S1/$INDEX
    regex=("${regex[@]}" -e "s|S1/0/1|S1/$INDEX|g")

    # Replace (something)Ethernet with Ethernet
    regex=("${regex[@]}" -e "s|[A-Za-z]*Ethernet|Ethernet|g")

    # Apply.
    sed "${regex[@]}" "$IN" > "$OUT" || exit $?

    # Make sure new file has the same owner and mode
    chown --reference="$IN" "$OUT" &>/dev/null
    chmod --reference="$IN" "$OUT" &>/dev/null
done
Obviously if you have some expressions that are only applied to specific files, you could easily add a case statement adding such, i.e. just before applying the sed command, add
Code:
    case "$OUT" in
    R7)  regex=("${regex[@]}" -e "s|foo|bar|g") ;;
    R11) regex=("${regex[@]}" -e "s|baz|foo|g") ;;
    esac
or, if the regex sets overlap -- remember that only one case is selected and applied in a case statement in Bash --, perhaps
Code:
    if [ "$OUT" = "R7" ] || [ "$OUT" = "R13" ]; then
        regex=("${regex[@]}" -e "s|foo|bar|g")
    fi
    if [ "$OUT" = "R11" ] || [ "$OUT" = "R13" ]; then
        regex=("${regex[@]}" -e "s|baz|foo|g")
    fi
Hope this helps,
 
Old 01-16-2012, 06:32 AM   #3
contra04
LQ Newbie
 
Registered: Sep 2011
Location: London UK
Distribution: centos_fedora_DEbian
Posts: 17

Original Poster
Rep: Reputation: Disabled
Hi thank you very much for the prompt reply - I will give this a try now. I'll write a set of psuedo rules and then convert them.

So what kind of variable is regex() ? I am terrible at bash scripting.

Last edited by contra04; 01-16-2012 at 06:52 AM.
 
Old 01-16-2012, 07:22 AM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Quote:
Originally Posted by contra04 View Post
So what kind of variable is regex() ?
regex is an array variable. See Arrays chapter in the the Bash Reference Manual for details.

As an example,
Code:
array=('first thing' foo 'bar' *.jpeg)
ls -1 "${array[@]}"
Code:
array=()
array=("${array[@]}" 'first thing')
array=("${array[@]}" foo)
array=("${array[@]}" 'bar')
array=("${array[@]}" *.jpeg)
ls -1 "${array[@]}"
Code:
ls -1 'first thing' foo 'bar' *.jpeg
all run ls with the exact same parameters.

Last edited by Nominal Animal; 01-16-2012 at 07:26 AM.
 
1 members found this post helpful.
Old 01-16-2012, 02:41 PM   #5
contra04
LQ Newbie
 
Registered: Sep 2011
Location: London UK
Distribution: centos_fedora_DEbian
Posts: 17

Original Poster
Rep: Reputation: Disabled
# \bin\bash
for OUT in r[1-6]* ; do
IN="$OUT.old"
mv -f "$OUT" "$IN" || exit $?
regex=()
if [ "$OUT" = "r1.txt" ] || [ "$OUT" = "r2.txt" ];then
regex=("${regex[@]}" -e "s|interface Serial 0\/0|interface Serial 1\/0|g")
#r1.txt
#interface Serial 0/0 --> interface Serial 1/0
#interface Serial 0/0.1 --> interface Serial 1/0.1
fi
#r2.txt
#interface Serial 0/0 --> interface Serial 1/0
#interface Serial 0/0.1 --> interface Serial 1/0.1
if [ "$OUT" = "r3.txt" ];then
regex=("${regex[@]}" -e "s|interface FastEthernet0\/0|interface Ethernet0\/0|g")
regex=("${regex[@]}" -e "s|interface FastEthernet0\/1|interface Ethernet0\/1|g")
fi

#r3.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1

if [ "$OUT" = "r4.txt" ] || [ "$OUT" = "r5.txt" ];then
regex=("${regex[@]}" -e "s|interface FastEthernet0\/0|interface Ethernet0\/0|g")
regex=("${regex[@]}" -e "s|interface FastEthernet0\/1|interface Ethernet0\/1|g")
regex=("${regex[@]}" -e "s|interface Serial 0\/0\/0|interface Serial 1\/0|g")
fi

#r4.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1
#interface Serial0/0/0 --> interface Serial1/0
#interface Serial0/0/0.1 point-to-point --> interface Serial1/0.1 point-to-point

#r5.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1
#interface Serial0/0/0 --> interface Serial1/0
#interface Serial0/1/0 --> interface Serial1/1

if [ "$OUT" = "r6.txt" ] ;then
regex=("${regex[@]}" -e "s|interface FastEthernet0\/0|interface Ethernet0\/0|g")
regex=("${regex[@]}" -e "s|interface Serial 0\/0\/0|interface Serial 1\/0|g")
fi

#r6.txt
#interface Serial0/0/0 --> interface Serial1/0
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/0.67 --> interface Ethernet0/0.67
#interface FastEthernet0/0.146 --> interface Ethernet0/0.146
echo $IN
echo $OUT
# Apply.
sed "${regex[@]}" "$IN" > "$OUT" || exit $?
chown --reference="$IN" "$OUT" &>/dev/null
chmod --reference="$IN" "$OUT" &>/dev/null
done


This is what I have so far and the changes I need to make in the comments. I figure that changing the subinterfaces will be covered by the global replace, e.g. 0/0 -> 1/0 and 0/0.1 -> 1/0.1 as the 0/0 and the 1/0 are the beginnings of the other. Was the escaping correct for the forward slashes?

also what is the $? character?

There is 20 different configs for each router, but the interface changes are always the same, so it would be great to bea able to send them through the script before pasting them onto the routers.

Last edited by contra04; 01-16-2012 at 03:15 PM.
 
Old 01-16-2012, 03:49 PM   #6
contra04
LQ Newbie
 
Registered: Sep 2011
Location: London UK
Distribution: centos_fedora_DEbian
Posts: 17

Original Poster
Rep: Reputation: Disabled
Ok awesome that worked now the last piece of the puzzle. Sed is just a monster to understand

I am trying to add a new line after every occurence of the "interface Ethernet0/*" the text in the new line sets the interfaces to full duplex.

so

interface Ethernet0/0

would become:

interface Ethernet0/0
Duplex Full

as would

interface Ethernet0/1

become


interface Ethernet0/1
duplex full

so far I have a mash up:

sed -e |interface Ethernet 0\/0.*|/a\Duplex Full|g r7.txt

any ideas on the syntax of this one?
 
Old 01-17-2012, 02:48 AM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Please use [CODE][/CODE] tags around code and exact strings. It keeps indentation intact, and makes it much easier to read.

Quote:
Originally Posted by contra04 View Post
regex=("${regex[@]}" -e "s|interface Serial 0\/0|interface Serial 1\/0|g")
No need to escape slashes, as the separator character is | . (At least GNU sed does not mind an extra backslash at all, so your version would work with it at least. To adhere to standards, drop the backslash there.)

These two sed commands do the exact same thing:
Code:
s|foo/bar|baz|g
s/foo\/bar/baz/g
The backslash is only necessary if the character would be interpreted differently otherwise.

Quote:
Originally Posted by contra04 View Post
also what is the $? character?
Each command has an exit status code. If the command is successful, the status is 0. If the command fails, the status is nonzero. $? is the status from the last command.

This also means that
Code:
some-command...
if [ $? -eq 0 ]; then
    echo "Successful"
else
    echo "Failed"
fi

if some-command... ; then
    echo "Successful"
else
    echo "Failed"
fi
both do and test the exact same thing: whether some-command... exit status was zero/success or nonzero/error.

Additionally,
Code:
some-command...
if [ $? -ne 0 ]; then
    exit $?
fi

if ! some-command... ; then
    exit $?
fi

some-command... || exit $?
all three do the same thing: they run some-command... and abort the script (using the same exit status as the command) if it failed, i.e. returned a non-zero exit status.

Quote:
Originally Posted by contra04 View Post
so far I have a mash up:
Code:
sed -e |interface Ethernet 0\/0.*|/a\Duplex Full|g r7.txt
any ideas on the syntax of this one?
How about
Code:
-e '/^[\t\v\f\r ]*interface[\t\v\f\r ]/ a\\Duplex full'
This one matches any line that begins with optional whitespace, word "interface", and a whitespace character, and inserts "Duplex full" before the next line. The interface line itself is not edited, it is kept intact; it's just used to find the spot where to add the new line.

Note that you seem to be having some issues with proper quoting. I recommend you take a look at the Quoting chapter in the Bash Reference Manual; the first three subsections (Escape Character, Single Quotes, and Double Quotes) are the most important.

Most of the problems I've seen in shell scripts stem for incorrect/bad quoting. You really should learn it first, and apply it always. I recommend "defensive quoting", i.e. using the strictest form of quoting that will work, even when quoting might not be technically required, and it has served me extremely well.

The most basic rules are actually quite simple:
  • Remember that the strings you write will be interpreted by the shell first. They're only given to the actual commands after the shell has applied its own magic first.
  • Single quotes '...' tell the shell to keep the content intact, not apply its magic to the contents. The single quote characters themselves are not given to the command, but whatever is between them is.
  • Double quotes "..." tell the shell to apply its magic to the contents, but keep the result as a single string, as a single parameter to the command.
    The shell will interpret escapes like \" and variable references like $foo and so on.
    Expressions "$@" and "${array[@]}" are exceptions to this rule. They expand the lists (positional parameters for the first, array items for the second) as individual parameters.
  • Omitting quotes tells the shell to split the words into separate parameters.
    Details depend on shell options, though.
  • Quotes can be joined. "a"'b'cde"f" is the same as 'abcdef' and abcdef .
    This is useful if you want to insert a variable into a complex string, such as a sed pattern.
    'this is the fixed string part'"$variable"'the fixed string part continues' is a single string to the shell.
The magic that the shell applies in different situations is described in Shell Expansions chapter in the Bash Reference Quide. It's a bit heavy chapter, but knowing the stuff in it does make script writing a whole lot easier. If you haven't found my replies too tedious to read, the chapters in the manual I've referred to here should be pretty easy to understand
 
1 members found this post helpful.
Old 01-17-2012, 03:38 PM   #8
contra04
LQ Newbie
 
Registered: Sep 2011
Location: London UK
Distribution: centos_fedora_DEbian
Posts: 17

Original Poster
Rep: Reputation: Disabled
I only need full duplex on 10meg ethernet interfaces, as 100 meg fast enthernet auto detects the correct speed. This is the one I got working in the end. It must look like spaghetti!

Code:
# \bin\bash
for OUT in r[1-6]* ; do
        IN="$OUT.old"
mv -f "$OUT" "$IN"  || exit $?
regex=()
echo $OUT
if [ "$OUT" = "r1.txt" ] || [ "$OUT" = "r2.txt" ];then
regex=("${regex[@]}" -e "s|interface Serial0/|interface Serial1/|g")
#r1.txt
#interface Serial 0/0 --> interface Serial 1/0
#interface Serial 0/0.1 --> interface Serial 1/0.1
fi
#r2.txt
#interface Serial 0/0 --> interface Serial 1/0
#interface Serial 0/0.1 --> interface Serial 1/0.1
if [ "$OUT" = "r3.txt" ];then
regex=("${regex[@]}" -e "s|interface FastEthernet0/0|interface Ethernet0/0|g")
regex=("${regex[@]}" -e "s|interface FastEthernet0/1|interface Ethernet0/1|g")
fi

#r3.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1

if [ "$OUT" = "r4.txt" ] || [ "$OUT" = "r5.txt" ];then
regex=("${regex[@]}" -e "s|interface FastEthernet0/0|interface Ethernet0/0|g")
regex=("${regex[@]}" -e "s|interface FastEthernet0/1|interface Ethernet0/1|g")
regex=("${regex[@]}" -e "s|interface Serial0/0/0|interface Serial1/0|g")
regex=("${regex[@]}" -e "s|interface Serial0/1/0|interface Serial1/1|g")
fi

#r4.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1
#interface Serial0/0/0 --> interface Serial1/0
#interface Serial0/0/0.1 point-to-point --> interface Serial1/0.1 point-to-point

#r5.txt
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/1 --> interface Ethernet0/1
#interface Serial0/0/0 --> interface Serial1/0
#interface Serial0/1/0 --> interface Serial1/1

if [ "$OUT" = "r6.txt" ] ;then
regex=("${regex[@]}" -e "s|interface FastEthernet0/0|interface Ethernet0/0|g")
regex=("${regex[@]}" -e "s|interface Serial0/0/0|interface Serial1/0|g")
fi
regex=("${regex[@]}" -e ' / Ethernet/ a\\ duplex full')
#r6.txt
#interface Serial0/0/0 --> interface Serial1/0
#interface FastEthernet0/0 --> interface Ethernet0/0
#interface FastEthernet0/0.67 --> interface Ethernet0/0.67
#interface FastEthernet0/0.146 --> interface Ethernet0/0.14

# Apply.
sed "${regex[@]}" "$IN" > "$OUT" || exit $?
chown --reference="$IN" "$OUT" &>/dev/null
chmod --reference="$IN" "$OUT" &>/dev/null
done
I guess I have a lot of reading to do, well got alot of configs to do a work for a xymon server so I guess Ill have a good reason to sharpen up.
Thank you for all of your help.
 
  


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] seek advice on pyqt3 task gary_in_springhill Programming 1 03-23-2010 07:43 PM
Event based task scheduler? beeblequix Linux - Software 1 01-30-2008 11:49 AM
SED;find and replace;help required gd13 Programming 3 12-21-2004 06:33 AM
Advice Required Goblin Linux - Networking 12 08-26-2003 08:34 AM
Advice required kabads Linux - General 2 10-11-2002 07:11 AM


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

Main Menu
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