tags:

views:

155

answers:

3

I'm trying to edit a text file that looks like this:

TYPE=Ethernet
HWADDR=00:....
IPV6INIT=no
MTU=1500
IPADDR=192.168.2.247
...

(Its actually the /etc/sysconfig/network-scripts/ifcfg- file on red hat Linux) Instead of reading and rewriting the file each time I want to modify it, I figured I could use grep, sed, awk or the native text parsing functionality provided in Perl.

For instance, if I wanted to change the IPADDR field of the file, is there a way I can just retrieve and modify the line directly? Maybe something like

grep 'IPADDR=' <filename> 

but add some additional arguments to modify that line? I'm a little new to UNIX based text processing languages so bear with me...

Thanks!

A: 

That would be the 'ed' command line editor, like sed but will put the file back where it came from.

Don
+1  A: 

since you are on redhat, you can try using the shell

#!/bin/bash

file="file"
read -p "Enter field to change: " field
read -p "Enter new value: " newvalue
shopt -s nocasematch
while IFS="=" read -r f v
do
    case "$f" in
        $field)
            v=$newvalue;;
    esac
    echo "$f=$v"
done <$file > temp
mv temp file

UPDATE:

file="file"
read -p "Enter field to change: " field
read -p "Enter new value: " newvalue
shopt -s nocasematch
EOL=false
IFS="="
until $EOL
do
    read -r f v || EOL=true
    case "$f" in
        $field)
            v=$newvalue;;
    esac
    echo "$f=$v"
done <$file #> temp
#mv temp file

OR , using just awk

awk 'BEGIN{
    printf "Enter field to change: "
    getline field < "-"
    printf "Enter new value: "
    getline newvalue <"-"
    IGNORECASE=1
    OFS=FS="="
}
field == $1{
    $2=newvalue
}
{
    print $0 > "temp"
}END{
    cmd="mv temp "FILENAME
    system(cmd)
}'  file

Or with Perl

printf "Enter field: ";
chomp($field=<STDIN>);
printf "Enter new value: ";
chomp($newvalue=<STDIN>);
while (<>){
    my ( $f , $v ) = split /=/;
    if ( $field =~ /^$f/i){
        $v=$newvalue;
    }
    print join("=",$f,$v);
}
ghostdog74
Thanks for your detailed responses! The bash script does exactly what I need except it removes the last line when the file is rewritten. Do I just need to add an EOF boolean to the while loop or what would you suggest?
synchronicity
that's strange. I don't have a problem with that. pls try the "new" version i edited.
ghostdog74
+8  A: 

Here's a Perl oneliner to replace the IPADDR value with the IP address 127.0.01. It's short enough that you should be able to see what you need to modify to alter other fields*:

perl -p -i.orig -e 's/^IPADDR=.*$/IPADDR=127.0.0.1/' filename

It will rename "filename" to "filename.orig", and write out the new version of the file into "filename".

Perl command-line options are explained at perldoc perlrun (thanks for the reminder toolic!), and the syntax of perl regular expressions is at perldoc perlre.

*The regular expression ^IPADDR=.*$, split into components, means:

  ^         # bind to the beginning of the line
  IPADDR=   # plain text: match "IPADDR="
  .*        # followed by any number of any character (`.` means "any one character"; `*` means "any number of them")
  $         # bind to the end of the line
Ether
... and the OP can look up the meaning of those `perl` switches from the commandline: `perldoc perlrun`
toolic
thanks for the reminder; it's good to always provide a reference for more info!
Ether