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

Hello I'm a Perl Baby and I'm trying to use a srcipt in order to make substitutions in a file File.txt picking up from an other file Address.txt. I found a rellay nice perl script and it work, but not enough for my specific situation Here is the code:

#!/usr/bin/perl use warnings; use strict; open( my $out_fh, ">", "output.txt" ) || die "Can't open the output fi +le for wri ting: $!"; open( my $address_fh, "<", "Address.txt" ) || die "Can't open the addr +ess file: $!"; my %lookup = map { chomp; split( /,/, $_, 2 ) } <$address_fh>; open( my $file_fh, "<", "File.txt" ) || die "Can't open the file.txt f +ile: $!"; while (<$file_fh>) { my @line = split; for my $char ( @line ) { ( exists $lookup{$char} ) ? print $out_fh " $lookup{$char} " : + print $ou t_fh " $char "; } print $out_fh "\n"; }

It works fine if in my File.txt words are separated with a space, but i need to make this working on files that use a | like separator, and even on xml files . Any ideas?. Cheers

Replies are listed 'Best First'.
Re: How to substitute a word with an other?
by Anonymous Monk on May 16, 2014 at 13:55 UTC

    Take a look at the documentation of split, all you would need to do to support a different character is change that line to something like this: my @line = split /\|/; (note the backslash is required because normally the pipe character is a special character in regular expressions, see perlre). An alternative way to write that is /\Q|/, the \Q causes the characters following it to lose their special meaning (documented in quotemeta).

    With XML things start getting more involved, for starters you'll need an XML module such as XML::Simple or XML::Twig to parse the XML, and then you'll need to walk through the data structures. If you're a beginner then perldsc might be a good place to start, as well as all the other tutorials that are a part of the Perl documentation - perlintro.

      Hi thanks for ur answer, but if I try to substitute the line

      my @line = split;

      with this one :

      my @line = split /\|/;;

      I just got in the output file the | is removed but it's not this my goal. I try to use your suggestion in the previous line:

      my %lookup = map { chomp; split( /\|/;, $_) } <$address_fh>

      but doesn't work Thanks for your help!

        "It doesn't work" does not help us to help you - please provide any error messages you are getting, and/or describe how the program currently behaves and how you'd like it to behave.

        Having said that, in your map you don't need the semicolon in /\|/;, since there is another argument to split ($_) following the regular expression, the statement doesn't end there. You said you are a Perl beginner, so have a look at perlintro (and perlsyn).

        To help your further could you provide a sample of what the three files (2x input 1x output) currently look like, and an example of how you'd like them to look? You can also edit your original post to include this information, see How do I change/delete my post?

Re: How to substitute a word with an other?
by Anonymous Monk on May 16, 2014 at 14:25 UTC

    Here's something to get you started with reading XML files with XML::Simple.

    #!/usr/bin/env perl use warnings; use strict; use XML::Simple qw/:strict XMLin/; my $xmldata = XMLin 'FILENAME.xml', ForceArray=>[], KeyAttr=>{};

    ... and you'll have the data from the XML file in $xmldata. To take a look at what that Perl data structure looks like, you can do this:

    use Data::Dumper; print Dumper($xmldata);

    Then, you would use the methods described in the sections "Access and Printing of ..." in perldsc to access the data structure in $xmldata (also read the "Common Mistakes" section, and really, the rest of the documentation too ;-)).

    One thing to note about XML::Simple is that in order to be "simple" to use, it simplifies the XML's structure a bit. For simple XML files it'll work very well, but if you have a complex input file or need to preserve the structure of the input file, that module may be too simple, in which case you can look at the many other XML modules on CPAN, such as XML::LibXML or XML::Twig.

    This is just an example of how to read the XML file. What you then do depends very much on what the XML file looks like, and what you want your program to do. Try it out, write some code, and if you need any help please feel free to ask, and provide sample input, your code with a description of what it's supposed to do, any error messages, and desired output (see also How do I post a question effectively?).

      Hi and thanks for your answer, I will try to be more effectively in my question! ;-) I have a file (File.txt in my code) with many lines like this one:

      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ServerName>RIGHTb4024</ServerName><DateTime>2013-04-22 10:53:22</DateTime><Application>SFMWW</Application><Function>Query</Function><UserNameOS>TESTER001</UserNameOS><UserNameApp>TESTER001</UserNameApp><LocationIP>17 2.31.8.71</LocationIP><LocationMachineName>RIGHTb4024</LocationMachineName><LocationMachineType/><LocationSessionID/><LocationRemoteIP/><LocationRemoteMachineName/><Lo cationRemoteUserName</LocationRemoteUserName><Customer>123456789016</Customer><Product>001007</Product><Operation>DET</Operation></SOAP-ENV:Body></SOAP-ENV:En velope>

      And what I need is to have an output file (Output.txt in my code) with a specific field value changed the like this

      <UserNameApp>TESTER001</UserNameApp>

      with

      <UserNameApp>Frank.Sinatra</UserNameApp>.

      Following a specific association in file Address.txt :

      TESTER001,Frank.Sinatra

      TESTER002,Cyndy.Crawford

      and so on .. Thanks for your help.

        Perhaps XML::Rules and its filter* methods would work for you?

        PerlMonks isn't a code writing service, but if you post the code you're having problems with, we'll be happy to help.