rsriram has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have tagged file stored in a string $str and I want to pick up all the footnotes placed at the end of the file and place it next to its reference inside the text. My code to do this is:

for ($i=0; $i <= $cnt; $i++)
{
$str =~ s/<fn id="fn$i">(.+)<\/fn>//g;
$found=$1;
$str =~ s/<fref id="fn${i}"\/>/<footnote id="en${i}">$found<\/footnote>/g;
}

$cnt contains the number of occurrences of footnotes. The first replacement of the footnote works well, but the subsequent replacements are not done correctly. Can anyone tell me what is the problem in the above syntax. The contents of $str is:

All businesses, regardless of their size, location, or mission, operate within a larger external environment. This external environment consists of everything outside an organization&#146;s boundaries that might affect it. Not surprisingly, the external environment plays a major role in determining the success or failure of any organization. Managers must therefore have a complete and accurate understanding of their environment and then strive to operate and compete within it. Of course, businesses can also influence their environments. To better explain the environment of business, we begin by discussing organizational boundaries, and then we introduce the concept of multiple organizational environments. Quite simply, an organizational boundary is that which separates the organization from its environment.<fref id="fn1"/> But whereas boundaries were once relatively easy to identify, they are becoming increasingly complicated and hard to pin down. Consider the simple case of a small neighborhood grocery that includes a retail customer area, a storage room, and an owner/manager&#146;s office.<fref id="fn2"/> In many ways, the store&#146;s boundary coincides with its physical structure: When you walk through the door, you&#146;re crossing the boundary into the business, and when you go back onto the sidewalk, you cross the boundary back into the environment.<fn id="fn1">See Waren J. Keegan, Global Marketing Management</fn><fn id="fn2">See James J. Kellenberger, Global Warming Management</fn>

Replies are listed 'Best First'.
Re: Replacing text in a string
by rodion (Chaplain) on Jul 19, 2006 at 11:50 UTC
    Can anyone tell me what is the problem in the above syntax.
    The first match is greedy (in Perl terms), it matches up to the terminating </fn> of the second footnote. Also, you don't want a "g" modifier at the end of the first match, since there should be only one "fn1" and only one "fn2", and you set $found to only one of them anyway.

    With these two changes made in that one line, the code works ok. The revised line is

    $str =~ s/<fn id="fn$i">(.+?)<\/fn>//;
    That takes care of your question and gets you on your way, but it's worth taking the time to work through Grandfather's code above, as you will learn some more advanced Perl techniques.
Re: Replacing text in a string
by GrandFather (Saint) on Jul 19, 2006 at 11:23 UTC

    Assuming this is not HTML and thus is appropriate for a simplistic search and replace the following code should get you started:

    use warnings; use strict; my $str = <<TEXT; All businesses, regardless of their size, location, or mission, operat +e within a larger external environment. This external environment consists of eve +rything outside an organization&#146;s boundaries that might affect it. Not surprisingly, the external environment plays a major role in determini +ng the success or failure of any organization. Managers must therefore have a + complete and accurate understanding of their environment and then strive to ope +rate and compete within it. Of course, businesses can also influence their envi +ronments. To better explain the environment of business, we begin by discussing organizational boundaries, and then we introduce the concept of multip +le organizational environments. Quite simply, an organizational boundary +is that which separates the organization from its environment.<fref id="fn1"/> + But whereas boundaries were once relatively easy to identify, they are bec +oming increasingly complicated and hard to pin down. Consider the simple cas +e of a small neighborhood grocery that includes a retail customer area, a sto +rage room, and an owner/manager&#146;s office.<fref id="fn2"/> In many ways, the store&#146;s boundary coincides with its physical structure: When you +walk through the door, you&#146;re crossing the boundary into the business, + and when you go back onto the sidewalk, you cross the boundary back into the environment.<fn id="fn1">See Waren J. Keegan, Global Marketing Management</fn><fn id="fn2">See James J. Kellenberger, Global Warming Management</fn> TEXT my @footnotes; push @footnotes, [$1, $2] while $str =~ m|<fn\s+id="(\w+)">((?:(?!</fn +>).)*)</fn>|gms; $str =~ s| <fref\s+id="\Q$_->[0]\E"/> | <footnote id="$_->[0]"$_->[1]<\/para><\/footnote> |gxms for @footnotes; print $str;

    Prints:

    All businesses, regardless of their size, location, or mission, operat +e within a larger external environment. This external environment consists of eve +rything outside an organization&#146;s boundaries that might affect it. Not surprisingly, the external environment plays a major role in determini +ng the success or failure of any organization. Managers must therefore have a + complete and accurate understanding of their environment and then strive to ope +rate and compete within it. Of course, businesses can also influence their envi +ronments. To better explain the environment of business, we begin by discussing organizational boundaries, and then we introduce the concept of multip +le organizational environments. Quite simply, an organizational boundary +is that which separates the organization from its environment. <footnote id="fn1"See Waren J. Keegan, Global Marketing Management</para></footnote> But whereas boundaries were once relatively easy to identify, they are bec +oming increasingly complicated and hard to pin down. Consider the simple cas +e of a small neighborhood grocery that includes a retail customer area, a sto +rage room, and an owner/manager&#146;s office. <footnote id="fn2"See James J. Kellenberger, Global Warming Management</para></footnote> In many ways, the store&#146;s boundary coincides with its physical structure: When you +walk through the door, you&#146;re crossing the boundary into the business, + and when you go back onto the sidewalk, you cross the boundary back into the environment.<fn id="fn1">See Waren J. Keegan, Global Marketing Management</fn><fn id="fn2">See James J. Kellenberger, Global Warming Management</fn>

    The replacement text looks rather broken to me, but that's from an HTML perspective so probably isn't relevant and is easily fixed in any case (probably). The main trick is to generate a list of footnote pairs up front, then perform a global search and replace for each footnote.


    DWIM is Perl's answer to Gödel