In Perl I can do the below and get the expected output admin1secretpw
.
How do I do the same in Ruby? I.e. save multiple buffers in variables.
#!/usr/bin/perl
my $a = 'admin1:[email protected]';
(my $u = $1, my $p = $2) if $a =~ /(.*?):(.*?)@/;
print $u;
print $p;
You can use named capture groups.
a = 'admin1:[email protected]'
/(?<username>.*?):(?<password>.*?)@/ =~ a
puts username
puts password
This captures both groups as local variables.
The order of arguments to =~
matters. Using ... =~ a
assigns the named groups to local variables, using a =~ ...
won't.
Please see the end for an important note on Perl code. With Ruby you can do
u, v = a.match(/(.*?):(.*?)@/)[1,2]
Here String#match is used. It recongizes /.../
as a regex, converts it to a Regexp object, and then invokes Regexp's match method on it. That returns a MatchData object, which acts as an array. Indexing with 0
gives the whole matched string while 1,2...
access array elements.
If a match fails nil
is returned so you can test for that, by if u.nil?
from NilClass.
An altogether cleaner way may be
if matched = a.match(/(.*?):(.*?)@/)
u, v = matched.captures
end
which uses MatchData#captures method. Or, you can use $1
and $2
inside the block.
Note that any code that defines symbols via regex matches on external data needs to test them.
There are other ways to do this in Ruby. As a curious example, you can do
u, v = (/(.*?):(.*?)@/).match(a)[1,2]
Here /.../
constructs a Regexp
object and then its match
method is invoked.
This can also be done nicely without regex, using String#split
u, v = a.split(/:|@/)[0..1]
The string a
is split using either :
or @
as a delimiter.
The question is stated with Perl code in a way that needs to be cleared up.
It appears that you intend to declare and assign conditionally. A statement such as my $x = 1
executes in two parts -- the declaration happens at compile time, while the assignment goes at runtime. Or, with that condition, it may not.
So, if the assignment doesn't happen at all ... then what value do we have? Also, the condition formally implies that the declaration may not happen at all†, which is impossible (the declaration does happen at compile time, before the if
is even considered); this makes the whole statement broken in a sense.
From Statement Modifiers in perlsyn (original emphasis)
NOTE: The behaviour of a
my
,state
, orour
modified with a statement modifier conditional or loop construct (for example,my $x if ...
) is undefined. The value of themy
variable may beundef
, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.
So you do not want to do that in Perl. Besides, regex gives you that for free
my ($u, $v) = $var =~ /(.*?):(.*?)@/;
Now test $u
and $v
. You can also do that in the same statement, if you wish
if ( my ($u, $v) = $var =~ /(.*?):(.*?)@/ ) {
print "$u, $v\n";
}
The condition is true only if both $u
and $v
are true. This may be very handy since $u
and $v
are now scoped in a convenient way but it can also be tricky if the regex can match and leave a variable(s) falsey, so use with care.
† That would be processed in the sense of ( my $var = ... ) if ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With