views:

384

answers:

11

I have a string like this

field1=1 field2=2 field3=abc

I want to ouput this as

2,1,abc

Any ideas as to how I can go about this? I can write a small C or Java program to do this, trying I'm trying to find out a simple way to do it in Perl.

+1  A: 

There's several ways you can do that:

  • Regex match
my $s = "field1=1 field2=2 field3=abc";
$s =~ /field1=(\w*) field2=(\w*) field3=(\w*)$/; //pick out each field
print $1,$2,$3;'
12abc
  • Split the string on match
my $s = "field1=1 field2=2 field3=abc"; 
my @arr = split / /, $s; print @arr,"\n"; //make an array of name=value pairs
my @vals = map { @pairs = split /=/, $_; $pairs[1] } @arr;  //get the values only from each pair
print @vals'
field1=1field2=2field3=abc
12abc
  • Split and put in a hash (I think that's the most useful one)
my $s = "field1=1 field2=2 field3=abc"; 
my @arr = split / /, $s;  
my %pairs = map { split=/, $_; } @arr; 
print $pairs{field1}, $pairs{field2}, $pairs{field3}
12abc
+2  A: 

Use m//g in list context:

#!/usr/bin/perl

use strict;
use warnings;

my $x = "field1=1 field2=2 field3=abc";

if ( my @matches = $x =~ /(?:field[1-3]=(\S+))/g ) {
    print join(',', @matches), "\n";
}

__END__

Output:

C:\Temp> klm
1,2,abc
Sinan Ünür
A: 

Assuming your ordering was a typo:


#!/usr/bin/perl
use strict; use warnings;

my $str='a=1 b=2 c=abc';
my @v;
while ($str =~ /=(\S+)/g) {
    push @v, $1;
}
print join (',', @v);
Marius Kjeldahl
There's no need to loop. You can grab all the matches at once by using `m//g` in list context.
Michael Carman
A: 

Perl is definitely the right tool for this.


#! /usr/bin/perl

$str = "field1=1 field2=2 field3=abc";
$str =~ /field1=(\S+)\ field2=(\S+)\ field3=(\S+)/;
print "$1,$2,$3", "\n";
Dima
and regexp is not :)
zakovyrya
+5  A: 
#!/usr/bin/perl

use strict;
use warnings;

# Input string
my $string = "field1=1 field2=2 field3=abc";
# Split string into a list of "key=value" strings
my @pairs = split(/\s+/,$string);
# Convert pair strings into hash
my %hash = map { split(/=/, $_, 2) } @pairs;
# Output hash
printf "%s,%s,%s\n", $hash{field2}, $hash{field1}, $hash{field3};   # => 2,1,abc
# Output hash, alternate method
print join(",", @hash{qw(field2 field1 field3)}), "\n";
Lars Haugseth
+1 for not resorting to the regex hammer. However: split(/\s+/,$string) is also more simply expressed as split(' ',$string)
glenn jackman
True, as long as there are single spaces only.
Lars Haugseth
+6  A: 
use strict;
use warnings;

my $string = 'field1=1 field2=2 field3=abc';
my @values = ($string =~ m/=(\S+)/g);
print join(',', @values), "\n";
Michael Carman
This outputs the fields in the wrong order.Minor nitpick: it also won't work if any of the values contain an equal sign.
Lars Haugseth
+2  A: 
 $_='field1=1 field2=2 field3=abc';
 $,=',';
 say /=(\S+)/g

Let's play Perl golf :D

jeje
That is a good one :)
zakovyrya
If we're playing golf... `perl -E "$_='field1=1 field2=2 field3=abc';$,=',';say /=(\S+)/g"`
Michael Carman
+1  A: 
my $str = 'field1=1 field2=2 field3=abc';
print(join(',', map { (split('=', $_))[1] } split(' ', $str)));
zakovyrya
A: 
my $a = "field1=1 field2=2 field3=abc";
my @f = split /\s*\w+=/, $a;
shift(@f);
print join(",", @f), "\n";
Alex Pavlov
A: 
$string="field1=1 field2=2 field3=abc";
@s=split /\s+/,$string;
$temp=$s[1];$s[1]=$s[0];$s[0]=$temp;
foreach (@s){s/.*=//; push(@a,$_ );}
print join(",",@a);
ghostdog74
A: 

If you actually need both the keys and the values. I would put them into a hash. You could just capture both sides of the "=", and put directly into the hash.

use strict;
use warnings;

my $str = 'field1=1 field2=2 field3=abc';

my %fields = $str =~ / (\S+) \s* = \s* (\S+) /xg;

use YAML;
print Dump \%fields
---
field1: 1
field2: 2
field3: abc

For further information please read perldoc perlre.

If you are just a beginner, you may want to read perldoc perlretut.

Brad Gilbert