Go Back   The macosxhints Forums > OS X Help Requests > UNIX - General



Reply
 
Thread Tools Rate Thread Display Modes
Old 10-29-2003, 08:36 AM   #1
tas
Triple-A Player
 
Join Date: Nov 2002
Location: Frankfurt, Germany
Posts: 167
easy one for perl experts

Ok, excuse me for being lazy, I could try and chase it down in tutorials, but maybe one of the gurus will just smile and know what has to be done: I want to tell perl to make a set of substitutions within a text file but ONLY for chunks of text that are inside curly brackets like so:
Code:
blah{arrglbarrgl}
These brackets appear randomly (i.e. not at beginning of lines). I want all other text to be left alone, but within the brackets every "X" replace by a "Y". I figure it must be the "lookahead expression," but how do I use it? Thanks guys!!!
tas is offline   Reply With Quote
Old 10-29-2003, 11:20 AM   #2
hayne
Site Admin
 
Join Date: Jan 2002
Location: Montreal
Posts: 32,473
There likely is a better way but I think the following should work as long as there is only one X inside each {}:

s/({[^}]*)X([^}]*})/$1Y$2/g

Explanation:
{[^}]* matches { followed by any number of non-} characters
[^}]*} matches any number of non-} characters followed by }
Putting these patterns in parentheses () captures the text into $1 and $2

Last edited by hayne; 10-29-2003 at 11:24 AM.
hayne is offline   Reply With Quote
Old 10-29-2003, 02:45 PM   #3
tas
Triple-A Player
 
Join Date: Nov 2002
Location: Frankfurt, Germany
Posts: 167
hayne,
thanks, that works! But (you guessed it) there's more than one "X" to replace in every string. But that was a nice solution, I should have thought of that myself!
tas is offline   Reply With Quote
Old 10-30-2003, 01:05 AM   #4
pmccann
Major Leaguer
 
Join Date: Jan 2002
Location: Adelaide, South Australia
Posts: 470
You want ugly...

we got ugly...
Code:
#!/usr/bin/perl -w
use strict;
my $text="Something once out {in brackets more than once, more than once}
and {once more with once feeling} once again";
$text=~s/{(.*)}/$a=$1;$a=~s|once|twice|g;"{$a}"/eg;
print "$text\n";
Replace and rejig as required, but the essence is in there. Neater solutions welcome, this is a quick hack! Yep that's a substitution operator in a substitution slot. Ain't that cute?

Cheers,
Paul

Last edited by pmccann; 10-30-2003 at 01:09 AM.
pmccann is offline   Reply With Quote
Old 10-30-2003, 01:45 AM   #5
hayne
Site Admin
 
Join Date: Jan 2002
Location: Montreal
Posts: 32,473
Paul:
Don't you need that
{(.*)}
to be
{([^}]*}
in order to deal with the case where you have two (or more) braced enclosures on one line.
E.g.:
Like {this one case} within {this one line} of text
?
hayne is offline   Reply With Quote
Old 10-30-2003, 10:04 AM   #6
tas
Triple-A Player
 
Join Date: Nov 2002
Location: Frankfurt, Germany
Posts: 167
YESYESYES! It works and does exactly what I need! Thanks Paul, it's so wonderful to have you around here. My next project: understanding how this works (so @ hayne: it seems to do multiple substitutions even w/o your editing). But don't post the solution yet, let me try and figure it out myself. And: THANKS MAN!
tas is offline   Reply With Quote
Old 10-30-2003, 05:52 PM   #7
tas
Triple-A Player
 
Join Date: Nov 2002
Location: Frankfurt, Germany
Posts: 167
I think I understood how the script works (great, this subsitution within a substitution!). There was indeed a problem when I had more than one pair of {} on a line: the "greedy" regexp would jump to the last one and substitute everything in between. So I came up with this solution, which does seem to be working:
Code:
 $_ =~ s/({)(.+?)(})/$a=$2;$a=~tr|X|Y|;"{$a}"/eg;
How do you like it?
tas is offline   Reply With Quote
Old 10-30-2003, 07:24 PM   #8
pmccann
Major Leaguer
 
Join Date: Jan 2002
Location: Adelaide, South Australia
Posts: 470
Sorry, I really was asleep when I wrote that one! hayne is spot on. It should certainly be a non-greedy quantifier (.*? or .+? will both be OK) in my first version in order to stop the problem with multiple brackets in the same chunk. Goes to show that I needed a better test string! hayne's proposed solution will also work fine...

Anyway, the following shows it working OK:
Code:
#!/usr/bin/perl -w
use strict;
my $text="Something once out {once, more than once} once {once}
and once more {once more with once feeling} once again";
$text=~s/{(.*?)}/$a=$1;$a=~s|once|twice|g;"{$a}"/eg;
print "$text\n"
As for your version, Tas: looks cool, but you can ditch those brackets around the braces and change the $2 back to $1. The use of "tr" is good for simple situations: I had interpreted your "X" and "Y" as placeholders, not what you were literally trying to replace!

Cheers,
Paul
pmccann is offline   Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



All times are GMT -5. The time now is 05:49 PM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.