jspanos has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to write a simple script to convert old stock option symbols to a new symbol format. This should be simple, but I am very new to Perl.

This script should take a list of symbols from a text file, change them to the new format, and print them out. For example, I need to change A.TL5E001100.TAV to +TL\E5C1100.TAV.

When I run my script I get 2 errors:

1. Unrecognized escape \F passed through at Find.Replace.TAV.options.P2.pl line 33.

- so it is choking on the "\" and I am not sure how to tell Perl how to treat this as text. I tried single and double quotes.

2. Use of uninitialized value $NewSym in concatenation (.) or string at Find.Replace.TAV.options.P2.pl line 41, <FILE> line 590.

- I am trying to print the new symbols to a file and I am obviously not specifying the outputted values correctly.

# this is my script to translate TAV stock options. use strict; use warnings; open (OUTPUT, ">TAV.opt.rename.txt") || die "TAV.opt.rename.txt $!\n"; my @file = <TAV.stock.opt.oldsym.txt>; # my $OldSym; my $NewSym; foreach my $f (@file) { open (FILE, $f) || die "Could not open $f $!\n"; my $line; while ($line = <FILE>) { chomp ($line); if ($line =~ m/^A.TL5E00/) { $line =~ s/A.TL5E00/'+TL\E5C'/g; } elsif ($line =~ m/^A.TL5F00/) { $line =~ s/A.TL5F00/'+TL\F5C'/g; }

The line above is where it is choking on the "\" character

} $NewSym = $line; print OUTPUT "$NewSym\n"; }

Replies are listed 'Best First'.
Re: Substitute script for a newbie
by toolic (Bishop) on Jul 14, 2015 at 16:44 UTC
    Escape the backslash:
    $line =~ s/A.TL5F00/+TL\\F5C/g;

    Tip #1 from the Basic debugging checklist: diagnostics might give you a little more info (it didn't for me on Perl version 5.12, but it did for 5.14).

    Did you really want the print inside the while loop? while ( $line = <FILE> ) { is really the same as while (defined($line = <FILE>)) {. So, outside the while, $line is undefined.

    UPDATE: You can simplify the if/else code with this single substitution:

    use warnings; use strict; while (my $line = <DATA>) { $line =~ s/^A.TL5([EF])00/+TL\\${1}5C/g; print $line; } __DATA__ A.TL5E001100.TAV A.TL5F001100.TAV

      Thank you. One thing I should have mentioned is that I need to replace several different stock option symbols. That is why I have the elsif statement. There will be more.

      I also think that I am making this a lot more complex than it needs to be so I looked at an old script from a Perl lesson and I am going to use that. I will keep you posted.

        I would suppose that you have somewhere a file with a correspondence between old names and new names. If so, please provide a sample of that file so that we can figure out how to use it.

        The idea would be then to read this file and to load the information into a hash (old name = key, new name = value). Then you read your other file (the one you want to process), read the input, lookup into the hash and write the new name (to a new file).

        I can't give you much more details at this point. We would need to see a sample of the file with the translation (old to new name) as well as a sample of your input file.

Re: Substitute script for a newbie
by neilwatson (Priest) on Jul 14, 2015 at 17:47 UTC

    UPDATE, I reaped this against social norm. I had mentioned that I like extended regexes (/x) so that I can comment them. E.g.

    m/^A.TL5 ([EF]) # my match here 00/x

    I like this because later the comment will help me to remember what I was doing, and in general regexes can be hard to read. I mistakenly extended this to to s///.

    s/^A.TL5 ([EF]) # my match here 00 / NEW \s+ {$1} # replae here /x
    Toolic pointed out that extended regexes in s/// only work on the matching part, not the replacing part. So this, I hope, is the legal one:
    s/^A.TL5 ([EF]) # my match here 00 /NEW {$1}/x

    Neil Watson
    watson-wilson.ca

      The /x modifier only works for the PATTERN (left side) of the substitution operator; it does not work for the REPLACEMENT (right side). Run your code to confirm.
      Sorry, Neil, but this is not the right way to modify a post on this site. You should leave the original content and add corrections clearly marked as updates, possibly strike out your original text or code, but please do not remove or change content without telling explicitly that you are doing that.

      Right now, toolic's post make no longer sense, because you changed you post without leaving unchanged its original content.

      Thank you, Neil, for having quickly taken my advice into consideration and restored your post to something closely reflecting its original content. I'll upvote your post for that, despite the original mistake.