search and replace dynamic data in a shell script

Hi,

I have a file that looks something like this:

...
0,6,256,87,0,0,0,1187443420
0,6,438,37,0,0,0,1187443380
0,2,0,0,0,10,0,1197140320
0,3,0,0,0,10,0,1197140875
0,2,0,0,0,23,0,1197140332
0,3,0,0,0,23,0,1197140437
0,2,0,0,0,17,0,1197140447
0,3,0,0,0,17,0,1197140543
0,2,0,0,0,30,0,1197140237
0,3,0,0,0,30,0,1197140231
0,6,375,98,0,0,0,1187443420
0,6,222,11,0,0,0,1187443380
...

The number in the last column is dynamic. "0,2,0,0,0" is always followed by "0,3,0,0,0" What I need to do is as follows:

  • I need to find the first line that starts out with 0,2,0,0,0
  • Compare the column 6 to mynumber_1 (10) and if they match I move on to the next line
  • Make sure in the next line the column 6 is also 10
  • This time, I do the same thing with mynumber_2
  • I repeat until mynumber_4 (30 in this case) is found
  • Add two lines of my own data in between:

0,3,0,0,0,30,0,1197140231 and 0,6,375,98,0,0,0,1187443420

  • Basically, the end result should be new file with two more lines of data in the right place
  • In next iteration, I just have to get to the two new lines that I added and update the column6

I am thinking of doing the following:

  • cat each line and see if it starts with 0,2,0,0,0. Is there a easy way to do this? In Perl, you can check to see if your variable CONTAINS certain data. Can you do this in shell?

  • If it doesn't start out with 0,2,0,0,0 then cat $line >> new_file

  • If it does, check the subsequent lines until my last number is matched up in column 6.

  • If it fails during these subsequent checks, move on to the next line and start over with my_number1

Does this sound like a good algorithm? Any suggestions? I am currently stuck at checking each line to see if it starts out with 0,2,0,0,0. Thanks.

cat $line
will look for a file whose name is in the variable $line. I don't think that you want that.

I don't understand your algorithm at all. But let's say that I have data like this:
1,2,3
0,0,7
0,2,4
0,0,0
8,0,0
And I only want the lines where the first two numbers are 0. Now my simplified example could be solved very easily, but I'm going to show how to read those numbers and check the values....

#! /usr/bin/ksh
exec < inputfile
exec > outputfile
IFS=,
while read n1 n2 n3 ; do
          if (( n1 == 0 && n2 == 0)) ; then
                      echo ${n1},${n2},${n3}
          fi
done
exit 0

I hope this gets you pointed in the right direction.

i also have a similar problem that i spose could also come under "search and replace dynamic data in a shell script"
I am a mac user and am fairly new to the comand line and so don't know alot about shell scripts.
I want to know how to make a script that can either search an xml doc for a certain string or pattern or whatever(more specifically the value of a certain tag) and replace it with another or simply replace line #... with a specific string of text.

I've gotton so far as getting grep to find and output the text i want to replace(if that's of any use, i don't know) but i am lacking the knowledge of what to do next.

What should i do?

Well, Nat, the first thing you should do is to acquaint yourself with our search function. You can get some ideas by looking at some old threads. Here are a few....

Replace text in match files

Replace string and delete extra characters

String Substitution Question

First of all, your explanation is very confusing. You didn't explain what my_number_1(10) was. In any case, it seems that what you are trying to do is simple to do in Perl. To see if a line starts with "0,2,0,0,0" is trivial in Perl:

if ($line =~ /^0\,2\,0\,0\,0/) {

}

From what I can make of your algorithm, it seems like you want to do something along the lines of:

open(INPUT, "< inputfile");
open(OUTPUT, "> outputfile");

while ($line = <INPUT>) {

chomp $line; # remove the carriage return
if ($line =~ /^0\,2\,0\,0\,0/) {
#look for 0,2,0,0,0 at the beginning of the line

  @array = split\(/,/ , $line\);  \# split the line into parts

  if \($array[5] eq $mynumber_4\) \{

     $nextline = &lt;INPUT&gt;;  \# get the next line
     chomp $nextline;  \# remove the carriage return

    print OUTPUT "$line\\n$nextline\\n";

    \#\#  add your own 2 lines here
    print OUTPUT  $my_newline1;
    print OUTPUT  $my_newline2;

     next;
  \}

  if \($array[5] eq $mynumber_1\) \{

      $nextline = &lt;INPUT&gt;;  \# get the next line
      chomp $nextline;   \# remove the carriage return

      @array2 = split\(/,/ , $nextline\);  \#split the next line
      if \($array2[5] eq $mynumber_1\) \{
         print OUTPUT "$line\\n$nextline\\n";
      \}
  \} else \{
     \#\#  didn't find 0,2,0,0,0 .... write directly to output file
     print OUTPUT "$line\\n";
  \}

}

}

close(INPUT);
close(OUTPUT);

Again, this is the best I could make out from what you asked. I also left out a bunch of things like checking error conditions and delcaring variables as 'my'. In any case, it should be simple to do in Perl. I would recommend reading into Perl some more or get an experienced Perl programmer to help you out.

kowrip,

Thanks for your help. But if you read my post carefully, you'll see that I almost explicitly declined to do this in perl. I just have to do this in shell that's all... :-p

Perderabo,

That definitely helped. I guess I didn't do a good job of describing what I am faced with. The problem is actually a lot more complicated than what I posted. I was just trying to get an idea of how I'd get started. I have written 200 lines of code so far and counting...

At any rate, thanks everyone for your help!

Oops. I completely misread what you typed. You typed:

"In Perl, you can check to see ...."

I read this as:

"In Perl, CAN YOU check to see .... ?"

Sorry again. I feel like an idiot now. :rolleyes:

Perderabo,

Is there a way to set IFS only for reading in from inputfile? While I am reading in my lines, I want to do something like this:

for s in `echo $my_var | sed 's/./& /g'; do
blah...
done

But if my IFS is set to "," the above mentioned for-loop doesn't work. As a temporary solution, I unset IFS before the loop and reset IFS to "," after the loop. Is this the only way or is there another way? My way kinda seems dumb... :-p

Thanks.

I think that this will work....

while IFS=, read n1 n2 n3 ; do