[comp.lang.perl] Pattern Substitution Question

blurie@dg-rtp.dg.com (Benjamin Lurie) (10/27/90)

Here's a question, whose answer I'm sure is going to be trivial, that I've
been trying to resolve for days.  Given input like the following:

	Lurie;Benjamin;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343

I would like to translate it to:

	Benjamin Lurie;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343

I've tried a pattern match looking for a semi-colon, but I always get the
longest pattern that matches, which would include everything up to the "(w)".

What pattern substitution would accomplish what I want here?  And, in general,
how would I specify to match only the input up to the first ocurrance of 
<c>, where <c> is some specific character?

===============================================================================
Benjamin Lurie		blurie@einstein.webo.dg.com

Data General
Westboro, Mass
===============================================================================

merlyn@iwarp.intel.com (Randal Schwartz) (10/30/90)

In article <1086@dg.dg.com>, blurie@dg-rtp (Benjamin Lurie) writes:
| Here's a question, whose answer I'm sure is going to be trivial, that I've
| been trying to resolve for days.  Given input like the following:
| 
| 	Lurie;Benjamin;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
| 
| I would like to translate it to:
| 
| 	Benjamin Lurie;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
| 
| I've tried a pattern match looking for a semi-colon, but I always get the
| longest pattern that matches, which would include everything up to the "(w)".

assuming $_ = "Lurie...2343\n"... it'd be:

s/^([^;]*);([^;]*);/$2 $1;/;

Or, if you prefer thinking in fields, something like:

	@f = split(/;/);
	$_ = join(";", "$f[1] $f[0]", @f[2..$#f]);

and to be totally clean about it,

	chop if /\n$/;
	@f = split(/;/);
	$_ = join(";", "$f[1] $f[0]", @f[2..$#f]) . "\n";

(which works even if you move around the last field).

The last two are incorrect inside a general-purpose subroutine, which
ought to take $[ into consideration, but I'll presume that's not a
problem for you yet.

$_ = "another;Just;hacker;Perl"; @f = split(/;/); print "@f[1,0,3,2],";
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel put the 'backward' in 'backward compatible'..."=========/

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (10/30/90)

In article <1086@dg.dg.com> blurie@einstein.webo.dg.com writes:
: Here's a question, whose answer I'm sure is going to be trivial, that I've
: been trying to resolve for days.  Given input like the following:
: 
: 	Lurie;Benjamin;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
: 
: I would like to translate it to:
: 
: 	Benjamin Lurie;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
: 
: I've tried a pattern match looking for a semi-colon, but I always get the
: longest pattern that matches, which would include everything up to the "(w)".
: 
: What pattern substitution would accomplish what I want here?  And, in general,
: how would I specify to match only the input up to the first ocurrance of 
: <c>, where <c> is some specific character?

The general solution is to use a negated character class.  For semicolons,
say something like:

    while (<>) {
	s/^([^;]*);([^;]*);/$2 $1;/;
	print;
    }

However, if you're looking for readability it might be cleaner to say
something like:

	while (<>) {
	    ($lastname, $firstname, $rest) = split(/;/, $_, 3);
	    print "$firstname $lastname;$rest";
	}

And, believe it or not, it runs faster, at least on my machine.  You can
shave another 7-8% off by saying

	    print $firstname, ' ', $lastname, ';', $rest;

which avoids some string copying.

Larry

rubenst@ircam.ircam.fr (Brad Rubenstein) (11/02/90)

In article <1086@dg.dg.com> blurie@einstein.webo.dg.com writes:
>Here's a question, whose answer I'm sure is going to be trivial, that I've
>been trying to resolve for days.  Given input like the following:
>
>	Lurie;Benjamin;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
>
>I would like to translate it to:
>
>	Benjamin Lurie;1212 Nowhere Road;(617) 923-0000;(w) (000) 202-2343
>

s/^([^;]*);([^;]*)/$2 $1/

Brad

-- 
Brad Rubenstein, rubenst@ircam.fr	IRCAM - Service Syste`me