Do you have a question? Post it now! No Registration Necessary. Now with pictures!
- Posted on
- Parsing blocks of text in Perl
March 5, 2008, 8:35 pm
rate this thread
Perl 5.8.4 and only have access to the stock libraries, mostly.
What I need to do is parse through a text file and perform some
transformations on embedded link structures for a wiki content
conversion. A "link" is defined as anything wrapped in double
brackets - [[<string>]], which can appear anywhere in a line of text
and multiple links can appear in a line of text.
1) If the link has a colon (":") in it, I need to strip out all
special characters and spaces (everything except [a-zA_Z0-9]) from the
portion before the colon but leave the part after the colon intact.
[[Operation Intranet 2.0!:EvalHome|Eval Home]] -->
[[UP Platform:Home|UP Platform]] --> [[UPPlatform:Home|UP Platform]]
2) If the link does not have a ":" in it, I need to insert the string
General: before the name of the page.
[[Technical FAQs|Technical FAQs]] --> [[General:Technical FAQs|
[[Embedded - Top 5 content|Top 5 content]] [[General:Embedded - Top 5
content|Top 5 content]]
3) Special case - don't change if it is an image link or if it is an
external link (only single  enclosure).
[[Image:BIhouse.jpg]] --> [[Image:BIhouse.jpg]]
[http://spss.wikicities.com/wiki/SPSS_Wiki SPSS Wiki] --> [http://
spss.wikicities.com/wiki/SPSS_Wiki SPSS Wiki]
I expect this is similar to some HTML parsing requirements, but I've
been hunting through my O'Reilly Perl books and Googling and I'm
having trouble finding my way. Normal regexp replace appears not to
be the way to go and I'm having greediness issues. Ideas?
Re: Parsing blocks of text in Perl
This implies that they cannot span more than one line of text, which is
what I assumed.
Removing everything except a-zA-Z0-9 from 'Image' doesn't change it.
Avoiding looking at single brackets would be easiest.
This is not nearly as complex as HTML, unles you haven't yet given us
all possible problems. I'm pretty sure that a regex can do that, and
greediness issues should, in this case, be simply fixable by using
non-greedy modifiers. If you have an example that doesn't get correctly
handled by the below, let us know.
Next time, before you post here, show us what you have tried first. This
is not a place where you can coe to get free code all the time, and if
you don't show us what you have tried, it looks like that is exactly
what you're trying to do.
For this time:
s/\[\[(.*?)\]\]/'[[' . replace_link($1) . ']]'/ge;
my @link = split ':', shift;
if (@link == 1)
unshift @link, 'General';
$link =~ tr/a-zA-Z0-9//dc;
return join ':', @link;
This can probably be made a bit faster, by avoiding splitting and
joining, but unless it's a problem I wouldn't worry about it. The
mechanism remains the same, and you shold be easily able to adjust
replace_link to taste. You could also avoid having to put the brackets
back by using look-(ahead|behind) assertions instead, but I generally
find this more readable. If links can cross line bondaries, and files
aren't too large, read the whole file in, and run the body of the while
loop on that.
Martien Verbruggen | Blessed are the Fundamentalists, for they
| shall inhibit the earth.
- » FAQ 4.62 Why don't my tied hashes make the defined/exists distinction?
- — Previous thread in » PERL Discussions