in reply to Script wont run

Hello cbtshare, and welcome to the Monastery!

Further to 1nickt’s post, if you open a file with +>> as the mode, the filehandle’s position is set to the end of the file. To read from the beginning, you need to add a seek:

seek XML, 0, 0;

However, as 1nickt says, this won’t solve the problem. You want to update passwords within the file, and appending new data at the end of the file can’t accomplish that.

One approach is to use the core module Tie::File:

use strict; use warnings; use Tie::File; my $filename = ...; tie my @array, 'Tie::File', $filename or die "Cannot tie file '$filename' to array: $!"; for my $line (@array) { my $newline = $line; # Make a copy while ($line =~ / Name=(.*?) \s+ Password=(.*?) (?:\s+|$) /gx) { my $name = $1; my $password = $2; print "Enter the plain text password for $name, ", "password is currently '$password'\n"; chomp(my $newpass = <>); print "You will now swap $password for Password='$newpass'\n"; print "Continue? (y/n)\n"; chomp(my $answer = <>); # Change the copy $newline =~ s{Password=\Q$password\E}{Password=$newpass} if $answer =~ /y/i; } $line = $newline; # Update this line in the file } untie @array or die "Cannot untie file '$filename': $!";

Note that it’s necessary to make the progressive password substitutions to a copy of $line, because changing $line within the while loop resets the /g match position, resulting in an infinite loop. See, e.g., “Global matching” in Using regular expressions in Perl.

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Script won't run
by cbtshare (Monk) on Nov 22, 2015 at 11:46 UTC
    Ok, thank you all for your comments and new approach, I will give the new approach a try now and let you know. also, I should have mentioned this is the structure of the file I am reading:
    <Node Name="MUN" Type="Connection" Descr="" Icon="mRemoteNG" Panel="Ge +neral" Username="root" Domain="" Password="a/5pqLSsMnvRfylxdN6coiFTdc +2+$ <Node Name="ubunugit" Type="Connection" Descr="" Icon="mRemoteNG" Pane +l="General" Username="root" Domain="" Password="bBxKPKXIhw1wKEV9aEUN1 +yynoRGOWT$ </Node>
    Thank you

      I meant to say earlier, if your input is XML — as indicated by the file extension and filehandle name in your OP — then you’ll be better off reading it with a dedicated module, such as XML::LibXML or XML::Twig.

      However, the file excerpt you show here is not valid XML.

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re^2: Script won't run
by cbtshare (Monk) on Nov 22, 2015 at 21:13 UTC
    Thank you Athanasius for your input and sample script, it works, but I have an issue with the formatting. the line below
    print "Enter the plain text password for $name, ", "password is currently '$password'\n";
    print out the entire line but I want only the name and password to show up it shows
    Enter the plain text password for "Q9" Type="Container" Expanded="True +" Descr="" Icon="mRemote" Panel="General" Username="" Domain="", pass +word is currently '""'
    I tried the following to just get the name and password only but it only returns 0 and 1 lol
    my @names = grep /\bName=(.*?)/ , @array; my @password = grep /\bPassword=(.*?)/ , @array; my $newline = $line; # Make a copy print "name is $names[0] and password is $password[0]\n";
    Also can you please tell me what the following means from your code.
    ?:\s+|$) /mgx also Q$password\E}
      ... can you please tell me what the following means from your code.

      ?:\s+|$) /mgx
      also

      Q$password\E}

      This should be  (?:\s+|$) (a non-capturing grouping),
      and  s{Password=\Q$password\E}{...} (the match regex of a substitution).

      To explain these:

      c:\@Work\Perl\monks>perl -wMstrict -le "use YAPE::Regex::Explain; ;; print YAPE::Regex::Explain->new('(?:\s+|$)')->explain; ;; my $password = 'f+o*o?[ ]b{}r'; my $regex = qr/Password=\Q$password\E/; print YAPE::Regex::Explain->new($regex)->explain; " The regular expression: (?-imsx:(?:\s+|$)) matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- (?: group, but do not capture: ---------------------------------------------------------------------- \s+ whitespace (\n, \r, \t, \f, and " ") (1 or more times (matching the most amount possible)) ---------------------------------------------------------------------- | OR ---------------------------------------------------------------------- $ before an optional \n, and the end of the string ---------------------------------------------------------------------- ) end of grouping ---------------------------------------------------------------------- ) end of grouping ---------------------------------------------------------------------- The regular expression: (?-imsx:Password=f\+o\*o\?\[\ \]b\{\}r) matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- Password=f 'Password=f' ---------------------------------------------------------------------- \+ '+' ---------------------------------------------------------------------- o 'o' ---------------------------------------------------------------------- \* '*' ---------------------------------------------------------------------- o 'o' ---------------------------------------------------------------------- \? '?' ---------------------------------------------------------------------- \[ '[' ---------------------------------------------------------------------- \ ' ' ---------------------------------------------------------------------- \] ']' ---------------------------------------------------------------------- b 'b' ---------------------------------------------------------------------- \{ '{' ---------------------------------------------------------------------- \} '}' ---------------------------------------------------------------------- r 'r' ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------
      Remember that  \Q...\E metaquotes any non-\w character literal or interpolated character. See the  \Q \L \l \U \u \E interpolation control escape sequences in Quote and Quote-like Operators in perlop; see also quotemeta.


      Give a man a fish:  <%-{-{-{-<

        Thank you very much , this helped alot. I am still having a bit of trouble with the script,it will not update the file, unless $line = $newline; is inside the while loop

        while ($line =~ / Name=(.*?) \s+ Password=(.*?) (?:\s+|$) /mgx) { my $name = $1; my $password = $2; print "Enter the plain text password for $name, ", "password is currently '$password'\n"; chomp(my $newpass = <>); print "You will now swap $password for password='$newpass'\n"; print "Continue? (y/n)\n"; chomp(my $answer = <>); # Change the copy $newline =~ s{Password=\Q$password\E}{Password=$newpass} if $answer =~ /y/i; } $line = $newline; # Update this line in the file } untie @array or die "Cannot untie file '$filename': $!";
        I apologize,after analyzing I realized that the file would be updated after the while loop ends , I was pressing CTRL + C to see if the file is being written to correctly. I do have other questions if you can please bear with me:
        s{Password=\Q$password\E}{Password=$newpass} if $answer =~ /y/i;
        wrapping the old password with \Q\E means that it will remain unchanged evidenced by : The sentence remain unchanged, so why do \q\e instead of just doing s{$password}{$newpass}
        my $sentence = 'The quick brown fox jumped over the lazy dog'; my $substring = 'quick.*?fox'; $sentence =~ s{\Q$substring\E}{big bad wolf};
        The script I ended working with is , do you have any recommendations or critque, and also can you suggest how I could get it to update immediately to the file instead of waiting till the loop ends?
        #!/usr/bin/perl use strict; use warnings; use Tie::File; my $filename = '/home/stain/Downloads/REMOTEopen.xml'; tie my @array, 'Tie::File', $filename || die "Cannot tie file $filenam +e to array: $!"; foreach my $line (@array) { my $newline = $line; # Make a copy while ($line =~ / <Node \s+ Name="(.*?)" .*? Password="(.*?)" +.*? > /mgx) { my $name = $1; my $password = $2; print "Enter the plain text password for $name, ", "password is currently $password\n"; chomp(my $newpass = <>); print "You will now swap $password for $newpass\n"; print "Continue? (y/n)\n"; chomp(my $answer = <>); # Change the copy $newline =~ s{$password}{$newpass} if $answer =~ /y/i; } $line = $newline; # Update this line in the file } untie @array or die "Cannot untie file '$filename': $!";
        Thank you for the help thus far, I managed to modify the script a bit an get it to grab the relevant info, but the issue now is that it is still not updating the file.Please have a look.
        #!/usr/bin/perl use strict; use warnings; use Tie::File; my $filename = '/home/stain/Downloads/REMOTEopen.xml'; tie my @array, 'Tie::File', $filename or die "Cannot tie file $filenam +e to array: $!"; foreach my $line (@array) { my $newline = $line; # Make a copy while ($line =~ / <Node \s+ Name="(.*?)" .*? Password="(.*?)" + .*? > /mgx) { my $name = $1; my $password = $2; print "Enter the plain text password for $name, ", "password is currently $password\n"; chomp(my $newpass = <>); print "You will now swap $password for $newpass\n"; print "Continue? (y/n)\n"; chomp(my $answer = <>); # Change the copy #$newline =~ s{Password=\Q$password\E}{Password=$newpass} if $ +answer =~ /y/i; $newline =~ s{\Q$password\E}{$newpass} if $answer =~ /y/i; } $line = $newline; # Update this line in the file } untie @array or die "Cannot untie file '$filename': $!";