How to automate edit of a file

I have a list of IP in a CSV file and need to add aditional lines ie,

the file is set as such, site#,device#,IP,DefaultGW,Netmask
S0033,3,10.10.39.10,10.10.39.1,255.255.255.0
S0033,3,10.10.39.11,10.10.39.1,255.255.255.0
S0033,3,10.10.39.12,10.10.39.1,255.255.255.0
all sites have the last octet of the IP for 1st device as .10 I have duplicated the lines for device 1 as many times as the number of devices in each site, example above site 0033 has 3 devices as indicated by the Site#,device# values.
what I need is to be able to run a command that will cat the list and for each site (using S0033 as example) where the site has 3 devices and edit the device values to as per above 3 devices so the outcome should be as below.
S0033,1,10.10.39.10,10.10.39.1,255.255.255.0
S0033,2,10.10.39.11,11.10.39.1,255.255.255.0
S0033,3,10.10.39.12,12.10.39.1,255.255.255.0

I hope I have explainned enough to get some bash command help to update the list as the file contains over 1800 lines and manual edit will take me hours if not days.
Apreciate any help,
Atorex
atorexAsked:
Who is Participating?
 
farzanjCommented:
Ok, check this one out.  I took out the troubleshooting marks but you can put them back if you like to.

Here's the code.
#!/bin/bash

SOURCE_FILE=$1
TARGET_FILE=$2

[[ -r $SOURCE_FILE ]] ||( "Cannot read $SOURCE_FILE" ; exit 1)

declare -A site

echo "$(<$SOURCE_FILE)" | while read line
do
    #Get site
    s=${line%%,*}
    #Increase count
    (( site[$s]++ ))
    ip3=$(echo $line | cut -f3 -d,| cut -f1-3 -d.)
    ip="$ip3."$(( ${site[$s]} + 9 ))

    echo "$s,${site[$s]},$ip,${line#*,*,*,}" >> $TARGET_FILE
done

Open in new window

0
 
farzanjCommented:
What is your bash version?
bash --version

Can you issue the following command?
site["S0033"]=1

0
 
farzanjCommented:
Sorry, also check if you can do
declare -A site

If you can then I can give you an easier solution
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

 
atorexAuthor Commented:
Bash is 4.2.8 on X64 Ubuntu 11
delcare -A can be used

Thanks.
0
 
farzanjCommented:
Try this:
#!/bin/bash

SOURCE_FILE=$1
TARGET_FILE=$2

declare -A site

echo "$(<$SOURCE_FILE)" | while read line
do
    #Get site
    s=${line%%,*}
    #Increase count
    (( site[$s]++ ))
    echo "$s,${site[$s]},${line#*,*,}" >> $TARGET_FILE
done

Open in new window

0
 
atorexAuthor Commented:
Thanks Farzanj,

Im getting the following when running the provided script, sorry for my lack of scripting knowledge but do I need to edit this in anyway like adding a source file name?

./TM_IP.sh: line 8: $SOURCE_FILE: ambiguous redirect
./TM_IP.sh: line 13: site[]: bad array subscript
./TM_IP.sh: line 13: site[]: bad array subscript
./TM_IP.sh: line 14: site: bad array subscript
./TM_IP.sh: line 14: $TARGET_FILE: ambiguous redirect
 
0
 
farzanjCommented:
Sorry, I couldn't write usage.

chmod 755 script.sh
./script.sh file new_file

You need to pass source file name and a new file name as command line parameter
0
 
atorexAuthor Commented:
I apreciate the help, I had the script set to executable however did not enter parameter, once I enter the parameter I get  bad array subscript on lines 13 and 14

./TM_IP.sh: line 14: site: bad array subscript
./TM_IP.sh: line 13: site[]: bad array subscript

much apreciated
0
 
farzanjCommented:
Here is how I ran it:
$ ./script log outlog

Here is how log looks like
S0033,3,10.10.39.10,10.10.39.1,255.255.255.0
S0033,3,10.10.39.11,10.10.39.1,255.255.255.0
S0033,3,10.10.39.12,10.10.39.1,255.255.255.0
S0034,3,10.10.39.12,10.10.39.1,255.255.255.0
S0035,3,10.10.39.12,10.10.39.1,255.255.255.0
S0034,3,10.10.39.12,10.10.39.1,255.255.255.0

Open in new window


And the outlog looks like this
 
S0033,1,10.10.39.10,10.10.39.1,255.255.255.0
S0033,2,10.10.39.11,10.10.39.1,255.255.255.0
S0033,3,10.10.39.12,10.10.39.1,255.255.255.0
S0034,1,10.10.39.12,10.10.39.1,255.255.255.0
S0035,1,10.10.39.12,10.10.39.1,255.255.255.0
S0034,2,10.10.39.12,10.10.39.1,255.255.255.0

Open in new window


Now try this one and it would create a file called error.log
Show me the contents.  make sure the input file is not too large
#!/bin/bash

SOURCE_FILE=$1
TARGET_FILE=$2

[[ -r $SOURCE_FILE ]] ||( "Cannot read $SOURCE_FILE" ; exit 1)

declare -A site

echo "$(<$SOURCE_FILE)" | while read line
do
    echo $line >> error.log
    #Get site
    s=${line%%,*}
    echo "s=$s" >> error.log
    #Increase count
    (( site[$s]++ ))
    echo "site=${site[$s]}" >> error.log
    echo "$s,${site[$s]},${line#*,*,}" >> $TARGET_FILE
done

Open in new window

0
 
atorexAuthor Commented:
Thanks so much for the help, I ran the new one and executed with no errors and I got the log attached, the site numbers are being changed but the last octet of the IP is not would you mind  adding that part as well, please? error.log
0
 
farzanjCommented:
Sorry, I don't understand the last octet part.  In your example above, it stayed the same.  Could you please elaborate?
0
 
atorexAuthor Commented:
ya sorry about that the last octet changes for each device example
device 1, IP 10.15.140.10
device 2, IP  10.15.140.11
device 3, IP 10.15.140.12

the last octet is to increase by 1 per device, I attemted to ajust what you gave me to do that and am able to change the IP but with my lack of scripting knowledge it deletes the Default GW so if you could help with that it would be much apreciated.
Thanks.
0
 
farzanjCommented:
So, I think you mean if you had
S0033,3,10.10.39.10,10.10.39.1,255.255.255.0
S0033,3,10.10.39.10,11.10.39.1,255.255.255.0
S0033,3,10.10.39.10,12.10.39.1,255.255.255.0

It should become
S0033,1,10.10.39.10,10.10.39.1,255.255.255.0
S0033,2,10.10.39.11,11.10.39.1,255.255.255.0
S0033,3,10.10.39.12,12.10.39.1,255.255.255.0
Correct?

It would be error prone though, because it may produce duplicates and it may exceed 255
0
 
farzanjCommented:
So question is, whether to change the given ip and add the device number minus 1 to it or store each devices' first instance's IP and add the device count minus one to it?
0
 
atorexAuthor Commented:
yes, thats correct as far as the error each location has no more then 5 devices so it would only go up to .14. To sumorize what you have given me is changing each device to a sequential number starting at 1, the qaditional part is to do the same with the IP within each location per device starting at .10.

Thanks.
0
 
atorexAuthor Commented:
I think adding the device number minus one  for the last octed would be acurate as all device 1 will have the last octet as .10 and goes up from there.
0
 
atorexAuthor Commented:
Perfect, that works as needed I cant thank you enough for all the help you have provide.
thanks so much and have a good new year.
0
 
atorexAuthor Commented:
AWSOME!!!
0
 
farzanjCommented:
Happy new year to you too.

Glad to help:)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.