📄 ch09_06.htm
字号:
<html><head><title>Substitutions with s/// (Learning Perl, 3rd Edition)</title><link rel="stylesheet" type="text/css" href="../style/style1.css" /><meta name="DC.Creator" content="Randal L. Schwartz and Tom Phoenix" /><meta name="DC.Format" content="text/xml" scheme="MIME" /><meta name="DC.Language" content="en-US" /><meta name="DC.Publisher" content="O'Reilly & Associates, Inc." /><meta name="DC.Source" scheme="ISBN" content="0596001320L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="Learning Perl, 3rd Edition" /><meta name="DC.Type" content="Text.Monograph" /></head><body bgcolor="#ffffff"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Learning Perl, 3rd Edition" /><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch09_05.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"></a></td><td align="right" valign="top" width="228"><a href="ch09_07.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">9.6. Substitutions with s///</h2><p><a name="INDEX-608" /> <a name="INDEX-609" /> <a name="INDEX-610" /> <a name="INDEX-611" />If you think of the<tt class="literal">m//</tt> pattern match as being like your wordprocessor's "search" feature, the "search andreplace" feature would have to be Perl's<tt class="literal">s///</tt> substitution operator. This simply replaceswhatever part of a variable<a href="#FOOTNOTE-205">[205]</a> matches a patternwith a replacement string:</p><blockquote class="footnote"> <a name="FOOTNOTE-205" /><p>[205]Unlike<tt class="literal">m//</tt>, which can match against any stringexpression, <tt class="literal">s///</tt> is modifying data that musttherefore be contained in what's known as an<em class="firstterm">lvalue</em>. This is nearly always a variable,although it could actually be anything that could be used on the leftside of an assignment operator.</p> </blockquote><blockquote><pre class="code">$_ = "He's out bowling with Barney tonight.";s/Barney/Fred/; # Replace Barney with Fredprint "$_\n";</pre></blockquote><p>If the match fails, nothing happens, and the variable is untouched:</p><blockquote><pre class="code"># Continuing from above; $_ has "He's out bowling with Fred tonight."s/Wilma/Betty/; # Replace Wilma with Betty (fails)</pre></blockquote><p>Of course, both the pattern and the replacement string could be morecomplex. Here, the replacement string uses the first memory variable,which is set by the pattern match:</p><blockquote><pre class="code">s/with (\w+)/against $1/;print "$_\n"; # says "He's out bowling against Fred tonight."</pre></blockquote><p>Here are some other possible substitutions. (These are here only assamples; in the real world, it would not be typical to do so manyunrelated substitutions in a row.)</p><blockquote><pre class="code">$_ = "green scaly dinosaur";s/(\w+) (\w+)/$2, $1/; # Now it's "scaly, green dinosaur"s/^/huge, /; # Now it's "huge, scaly, green dinosaur"s/,.*een//; # Empty replacement: Now it's "huge dinosaur"s/green/red/; # Failed match: still "huge dinosaur"s/\w+$/($`!)$&/; # Now it's "huge (huge !)dinosaur"s/\s+(!\W+)/$1 /; # Now it's "huge (huge!) dinosaur"s/huge/gigantic/; # Now it's "gigantic (huge!) dinosaur"</pre></blockquote><p>There's a return value from <tt class="literal">s///</tt>; it'strue if a substitution was successful; otherwise it's false:</p><blockquote><pre class="code">$_ = "fred flintstone";if (s/fred/wilma/) { print "Successfully replaced fred with wilma!\n";}</pre></blockquote><a name="lperl3-CHP-9-SECT-6.1" /><div class="sect2"><h3 class="sect2">9.6.1. Global Replacements with /g</h3><p>As you may have noticed in a previous example,<tt class="literal">s///</tt> will make just one replacement, even ifothers are possible. Of course, that's just the default. The<tt class="literal">/g</tt><a name="INDEX-612" /> modifier tells<tt class="literal">s///</tt> to make all possible nonoverlapping<a href="#FOOTNOTE-206">[206]</a> replacements:</p><blockquote class="footnote"><a name="FOOTNOTE-206" /><p>[206]It's nonoverlapping because each new match starts lookingjust beyond the latest replacement.</p> </blockquote><blockquote><pre class="code">$_ = "home, sweet home!";s/home/cave/g;print "$_\n"; # "cave, sweet cave!"</pre></blockquote><p>A fairly common use of a <a name="INDEX-613" />global replacement is to collapse<a name="INDEX-614" />whitespace; that is, to turnany arbitrary whitespace into a single space:</p><blockquote><pre class="code">$_ = "Input data\t may have extra whitespace.";s/\s+/ /g; # Now it says "Input data may have extra whitespace."</pre></blockquote><p>Once we show collapsing whitespace, everyone wants to know aboutstripping leading and trailing whitespace. That's easy enough,in two steps:<a href="#FOOTNOTE-207">[207]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-207" /><p>[207]It could be done in one step, but thisway is better.</p> </blockquote><blockquote><pre class="code">s/^\s+//; # Replace leading whitespace with nothings/\s+$//; # Replace trailing whitespace with nothing</pre></blockquote></div><a name="lperl3-CHP-9-SECT-6.2" /><div class="sect2"><h3 class="sect2">9.6.2. Different Delimiters</h3><p>Just as we did with <tt class="literal">m//</tt> and<tt class="literal">qw//</tt>, we can change the<a name="INDEX-615" />delimiters for<tt class="literal">s///</tt>. But the substitution uses three delimitercharacters, so things are a little different.</p><p>With ordinary (non-paired) characters, which don't have a leftand right variety, just use three of them, as we did with the forwardslash. Here, we've chosen the pound sign<a href="#FOOTNOTE-208">[208]</a>aSs the delimiter:</p><blockquote class="footnote"> <a name="FOOTNOTE-208" /><p>[208]Withapologies to our British friends, to whom the pound sign is somethingelse! Although the pound sign is generally the start of a comment inPerl, it won't start a comment when the parser knows to expecta delimiter -- in this case, immediately after the<tt class="literal">s</tt> that starts the substitution.</p> </blockquote><blockquote><pre class="code">s#^https://#http://#;</pre></blockquote><p>But if you use paired characters, which have a left and rightvariety, you have to use two pairs: one to hold the pattern and oneto hold the replacement string. In this case, the delimitersdon't have to be the same kind around the string as they arearound the pattern. In fact, the delimiters of the string could evenbe non-paired. These are all the same:</p><blockquote><pre class="code">s{fred}{barney};s[fred](barney);s<fred>#barney#;</pre></blockquote></div><a name="lperl3-CHP-9-SECT-6.3" /><div class="sect2"><h3 class="sect2">9.6.3. Option Modifiers</h3><p>In addition to the <tt class="literal">/g</tt> modifier,<a href="#FOOTNOTE-209">[209]</a> substitutionsmay use the <tt class="literal">/i</tt><a name="INDEX-616" /> and<tt class="literal">/s</tt><a name="INDEX-617" /> modifiers that we saw in ordinary patternmatching. The order of modifiers isn't significant.</p><blockquote class="footnote"> <a name="FOOTNOTE-209" /><p>[209]Wespeak of the modifiers with names like"<tt class="literal">/i</tt>" , even if the delimiter issomething different than a slash.</p> </blockquote><blockquote><pre class="code">s#wilma#Wilma#gi; # replace every WiLmA or WILMA with Wilmas{__END_ _.*}{}s; # chop off the end marker and all following lines</pre></blockquote></div><a name="lperl3-CHP-9-SECT-6.4" /><div class="sect2"><h3 class="sect2">9.6.4. The Binding Operator</h3><p>Just as we saw with <tt class="literal">m//</tt>, we can choose a differenttarget for <a name="INDEX-618" /><tt class="literal">s///</tt> by using thebinding operator:</p><blockquote><pre class="code">$file_name =~ s#^.*/##s; # In $file_name, remove any Unix-style path</pre></blockquote></div><a name="lperl3-CHP-9-SECT-6.5" /><div class="sect2"><h3 class="sect2">9.6.5. Case Shifting</h3><p>It often happens in a substitution that you'll want to makesure that a replacement word is properly capitalized (or not, as the<a name="INDEX-619" /><a name="INDEX-620" /><a name="INDEX-621" /><a name="INDEX-622" /><a name="INDEX-623" />case may be). That's easy toaccomplish with Perl, by using some backslash escapes. The<tt class="literal">\U</tt><a name="INDEX-624" /> escape forces what follows to alluppercase:</p><blockquote><pre class="code">$_ = "I saw Barney with Fred.";s/(fred|barney)/\U$1/gi; # $_ is now "I saw BARNEY with FRED."</pre></blockquote><p>Similarly, the <tt class="literal">\L</tt><a name="INDEX-625" /> escape forces lowercase. Continuingfrom the previous code:</p><blockquote><pre class="code">s/(fred|barney)/\L$1/gi; # $_ is now "I saw barney with fred."</pre></blockquote><p>By default, these affect the rest of the (replacement) string; or youcan turn off case shifting with<tt class="literal">\E</tt><a name="INDEX-626" />:</p><blockquote><pre class="code">s/(\w+) with (\w+)/\U$2\E with $1/i; # $_ is now "I saw FRED with barney."</pre></blockquote><p>When written in lowercase(<tt class="literal">\l</tt><a name="INDEX-627" /> and<tt class="literal">\u</tt><a name="INDEX-628" />), they affect only the next character:</p><blockquote><pre class="code">s/(fred|barney)/\u$1/ig; # $_ is now "I saw FRED with Barney."</pre></blockquote><p>You can even stack them up. Using <tt class="literal">\u</tt> with<tt class="literal">\L</tt> means "all lower case, but capitalize thefirst letter":<a href="#FOOTNOTE-210">[210]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-210" /><p>[210]The <tt class="literal">\L</tt> and<tt class="literal">\u</tt> may appear together in either order. Larryrealized that people would sometimes get those two backwards, so hemade Perl figure out that you want just the first letter capitalizedand the rest lowercase. Larry is a pretty nice guy.</p></blockquote><blockquote><pre class="code">s/(fred|barney)/\u\L$1/ig; # $_ is now "I saw Fred with Barney."</pre></blockquote><p>As it happens, although we're covering case shifting inrelation to substitutions, it's available in any double-quotishstring:</p><a name="INDEX-629" /><a name="INDEX-630" /><blockquote><pre class="code">print "Hello, \L\u$name\E, would you like to play a game?\n";</pre></blockquote></div><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch09_05.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"><img alt="Home" border="0" src="../gifs/txthome.gif" /></a></td><td align="right" valign="top" width="228"><a href="ch09_07.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">9.5. The Match Variables</td><td align="center" valign="top" width="228"><a href="index/index.htm"><img alt="Book Index" border="0" src="../gifs/index.gif" /></a></td><td align="right" valign="top" width="228">9.7. The split Operator</td></tr></table></div><hr width="684" align="left" /><img alt="Library Navigation Links" border="0" src="../gifs/navbar.gif" usemap="#library-map" /><p><p><font size="-1"><a href="copyrght.htm">Copyright © 2002</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"><area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -