Nesting Perl Regular Expressions

So, I am writing a quick perl script that clears some HTML code and runs it through an html -> pdf program. I want to lose as little information as possible, so I would like to expand my text fields to fit all the text that is currently in them. This means that in my case, setting the number of rows for the calculated value based on the value of the string inside the text field.

I am currently using regex

$file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)/80 })"$2>$3<\/textarea>/gis; 

Unfortunately, Perl does not seem to admit that they told me this is the syntax for embedding Perl code inside search and replace regular expressions. Are there any Perl addicts who want to tell me what I'm doing wrong? Regards, Zach

+7
regex perl
source share
6 answers

The pattern (?{...}) is an experimental function to execute code on the conformance side, but you want to execute code on the replacement side. Use the regular expression switch /e for this:

 #! /usr/bin/perl use warnings; use strict; use POSIX qw/ ceil /; while (<DATA>) { s[<textarea rows="(.+?)"(.*?)>(.*?)</textarea>] { my $rows = ceil(length($3) / 80); qq[<textarea rows="$rows"$2>$3</textarea>]; }egis; print; } __DATA__ <textarea rows="123" bar="baz">howdy</textarea> 

Output:

  <textarea rows = "1" bar = "baz"> howdy </textarea> 
+11
source share

The syntax you use to embed the code is only valid in the "match" part of the substitution (left). To paste the code on the right side (which is just a normal double-quoted string of Perl), you can do this:

 $file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>} {<textarea rows="@{[ length($3)/80 ]}"$2>$3</textarea>}gis; 

This uses the Perl idiom "some string @{[ embedded_perl_code() ]} more string" .

But if you are working with a very complex operator, it may be easier to put the substitution in "eval" mode, where it treats the replacement string as Perl code:

 $file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>} {'<textarea rows="' . (length($3)/80) . qq{"$2>$3</textarea>}}gise; 

Note that in both examples, the regular expression is structured as s{}{} . This not only eliminates the need to avoid slashes, but also allows you to spread the expression across multiple lines for readability.

+5
source share

Should this be done with regex? Parsing any markup language (or even CSV) with a regular expression is fraught with an error. If possible, try using the standard library:

http://search.cpan.org/dist/HTML-Parser/Parser.pm

Otherwise, you risk revenge on Cthulu:

http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html

(Yes, the article leaves room for simple string manipulations, so I think your soul is safe. :-)

+1
source share

I believe your problem is unsent /

If this is not a problem, it is certainly a problem.

Try this instead, pay attention to \/80

 $file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)\/80 })"$2>$3<\/textarea>/gis; 

The main template for this code:

 $file =~ s/some_search/some_replace/gis; 

gis are the options that I will need to look for. I think g = global, i = case insensitive, s = nothing comes to mind right now.

0
source share

First, you need to specify / inside the expression in the replacement text (otherwise perl will see the s /// operator, followed by the number 80 , etc.). Or you can use a different delimiter; for complex substitutions, parentheses are a good idea.

Then you get into the main problem, which is that (?{...}) is only available in templates. Replaceable text is not a pattern; it is an (almost) ordinary string.

Instead, there is an e modifier for the s/// operator, which allows you to write a replacement expression, not a replacement string.

 $ file = ~ s (<textarea rows = "(. +?)" (. *?)> (. *?) </textarea>)
           ("<textarea rows = \" ". (length ($ 3) / 80)." \ "$ 2> $ 3 </textarea>") egis;
0
source share

According to http://perldoc.perl.org/perlrequick.html#Search-and-replace , this can be done using the " s///e rating modifier", for example, you gis should have extra e .

The evaluation modifier s /// e wraps eval {...} around the replacement string, and the evaluation result is replaced with a substring. Some examples:

 # convert percentage to decimal $x = "A 39% hit rate"; $x =~ s!(\d+)%!$1/100!e; # $x contains "A 0.39 hit rate" 
0
source share

All Articles