-1

I am trying to write a basic Perl script to do some string manipulation. I get the "Existing_Value_To_Be_Changed" and the "New_Value" as user inputs.

The file has multiple block of lines such as the following -

foo_bar_xyz000123 := abcd (100010                                       
        01010111111001011010001010); - (Not in same line as previous)

The foo_bar_abc part of the string appears multiple times in the file. The only numbers following it uniquifies each appearance.

When I traverse line by line in Perl, how do I replace all the 0's(Existing_Value_To_Be_Changed) with 1's(New_Value) after the foo_bar_xyz has been matched (in all occurrences). But I need to start after the ( and keep going on to the following line(s) until the ); is encountered and stop after that.

Edit

I already completed the part about navigating my way into those specific blocks of lines. I am stuck in the character search & replacing part.

$var = 'false';
while <File> {
  if (pattern matches) {
    $var = 'true';
  }
  if ($var eq "true") {
    push(@array, $_);
    if ( $_ contains ");" ) {
      $var = 'false';
    }
  }
}

When the current line is stored in a variable, what is the best way to do the replace after the ( only until ); part?

Edit

The Existing_Value_To_Be_Changed and New_Value are user inputs, and if one is 0, then the other is 1 and vice versa as it is a binary string that contains only 0s and 1s.

Borodin
  • 126,100
  • 9
  • 70
  • 144
  • You can set a variable when you see the beginning of a block, and check that variable in your `while (<>)` loop to know if you're inside a block. Or when you see the beginning of a block you can start a nested loop that reads until the end of the block. – Barmar Jan 31 '15 at 19:55
  • What does the rest of the file look like? Would it be appropriate to change the record separator to semicolon `;`? How big is the file? – Borodin Jan 31 '15 at 19:57
  • Then you need to clarify what you have and how you want to process it. It reads as if *Existing_Value_To_Be_Changed* is always zero and *New_Value* is always one. – Borodin Jan 31 '15 at 19:59
  • So you're either changing everything to a 0 or everything to a 1? – Borodin Jan 31 '15 at 20:17
  • yes. that is correct – ClumsyCoder Jan 31 '15 at 20:17

1 Answers1

0

It is simplest to perform the translation as each multi-line sequence is found. This short program demonstrates.

You haven't described the content of your input file, so I have had to guess at some test data. The tr/0/1/r within the executable substitution is the part that changes the data.

use strict;
use warnings;
use 5.014;    # For non-destructive substitution

while (<DATA>) {
  if (/foo_bar_xyz000123/) {
    $_ .= <DATA> until /\);/;
    s| ( \( [01\s]+ \) ) | $1 =~ tr/0/1/r |ex;
  }
  print
}
__DATA__
xx
yy
zz
foo_bar_xyz000123 := abcd (100010                                       
        01010111111001011010001010);
aa
bb
cc
foo_bar_xyz000123 := abcd (100010                                       
        01010111111001011010001010
        01010111111001011010001010
        01010111111001011010001010); 
dd
ee
ff

output

xx
yy
zz
foo_bar_xyz000123 := abcd (111111                                       
        11111111111111111111111111);
aa
bb
cc
foo_bar_xyz000123 := abcd (111111                                       
        11111111111111111111111111
        11111111111111111111111111
        11111111111111111111111111); 
dd
ee
ff
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thanks Borodin. When I try your code, I get an error that says - Bareword found where operator expected at line 49, near "tr/0/1/r" Do you know why this is happening? – ClumsyCoder Jan 31 '15 at 20:51
  • I would guess that you are using an old version of Perl. I have used the non-destructive substitution modifier `/r`, which was introduced in version 14 of Perl 5 nearly four years ago. – Borodin Jan 31 '15 at 20:59
  • Thanks Borodin. I fixed that. You guessed the DATA correctly. That's pretty much how the file looks. The code compiled but my input DATA file is still the same. The 1's did not get converted to 0. foo_bar_xyz000123 := abcd (000011111110111 0010011100000100001110000010100100100001110101000111000011101110 1011101000111011001101101111100110010111001010010111110110011000); – ClumsyCoder Jan 31 '15 at 21:32
  • How much do you know about Perl? The idea is that the `DATA` file handle is convenient for a demonstration, and in use you should either `open` an input file and use that file instead, or you should put the input file name on the command line and use the null file handle to read from it, like `while ( <> ) { ... }` etc. It really depends on whether you want to change the program or change the command line to read from a different file. Likewise, the program sends its output to `STDOUT`. You can use `open` to open a file for output, or you could redirect `STDOUT` on the command line using `>`. – Borodin Jan 31 '15 at 22:02
  • If you want to edit the file in place then you should look at the `$^I` variable in [`perldoc perlvar`](http://perldoc.perl.org/perlvar.html). Which corresponds to the `-i` command-line switch [`perldoc perlrun`](http://perldoc.perl.org/perlrun.html). Either that if use can write to a different file and then use `rename` to name the original file as a backup and the new file as the original. – Borodin Jan 31 '15 at 22:07