BobMcGee
BobMcGee

Reputation: 20110

Why is this perl regex not doing DOTALL correctly?

I am using perl regex operations from the command line to modify a file (in linux), and want to know why it is failing to modify the file. Here is the regex:

perl -i -pe 'undef $/; s#(<web-app[^>]*>).*?(</web-app>)#\1CHEESE\n\2#gsi' filePath/web.xml

Now, this SHOULD be correctly matching multiline blocks. But, it isn't. Sample input:

<web-app xmlns= "http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
<stuff goes here and tags and things>
</web-app>

However nothing is changed. Dotall should be matching, and this works in an online regex testing tool,but fails with Perl. What am I doing wrong?

Upvotes: 1

Views: 912

Answers (2)

mpapec
mpapec

Reputation: 50647

You want to read whole file at once and make a substitution, and -0777 parameter does exactly that.

perl -i -0777 -pe 's#(<web-app[^>]*>).*?(</web-app>)#\1CHEESE\n\2#gsi' filePath/web.xml

previously $/ was set when first line was already read so regex couldn't match on partial content.

Upvotes: 7

Barmar
Barmar

Reputation: 781096

When you use the -p option, the script is inside the body of a while (<>) loop. So undef $/; won't be executed until after you get into the loop. So the first iteration will process the first line of input, and the second iteration will process the rest of the input.

You can insert code before the loop using a BEGIN block:

perl -i -pe 'BEGIN {undef $/;} s#(<web-app[^>]*>).*?(</web-app>)#\1CHEESE\n\2#gsi' filePath/web.xml

Upvotes: 2

Related Questions