📄 ch01_08.htm
字号:
<HTML><HEAD><TITLE>Recipe 1.7. Expanding and Compressing Tabs (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:28:52Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch01_01.htm"TITLE="1. Strings"><LINKREL="prev"HREF="ch01_07.htm"TITLE="1.6. Reversing a String by Word or Character"><LINKREL="next"HREF="ch01_09.htm"TITLE="1.8. Expanding Variables in User Input"></HEAD><BODYBGCOLOR="#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="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_07.htm"TITLE="1.6. Reversing a String by Word or Character"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 1.6. Reversing a String by Word or Character"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch01_01.htm"TITLE="1. Strings"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_09.htm"TITLE="1.8. Expanding Variables in User Input"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 1.8. Expanding Variables in User Input"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch01-chap01_expanding_0">1.7. Expanding and Compressing Tabs</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-745">Problem <ACLASS="indexterm"NAME="ch01-idx-1000010242-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010242-1"></A><ACLASS="indexterm"NAME="ch01-idx-1000010242-2"></A><ACLASS="indexterm"NAME="ch01-idx-1000010242-3"></A></A></H3><PCLASS="para">You want to convert tabs in a string to the appropriate number of spaces, or vice versa. Converting spaces into tabs can be used to reduce file size when the file has many consecutive spaces. Converting tabs into spaces may be required when producing output for devices that don't understand tabs or think they're at different positions than you do.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-751">Solution</A></H3><PCLASS="para">Either use a rather funny looking substitution:</P><PRECLASS="programlisting">while ($string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) { # spin in empty loop until substitution finally fails}</PRE><PCLASS="para">Or the standard Text::Tabs module:</P><PRECLASS="programlisting">use Text::Tabs;@expanded_lines = expand(@lines_with_tabs);@tabulated_lines = unexpand(@lines_without_tabs);</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-771">Discussion</A></H3><PCLASS="para">Assuming that tab stops are set every <EMCLASS="emphasis">N</EM> positions (where <EMCLASS="emphasis">N</EM> is customarily eight), it's easy to convert them into spaces. The standard, textbook method does not use the <ACLASS="indexterm"NAME="ch01-idx-1000010248-0"></A>Text::Tabs module but suffers from being difficult to understand. Also, it uses the <CODECLASS="literal">$`</CODE> variable, whose very mention currently slows down every pattern match in the program. The reason for this is given in the "Special Variables" section of the Introduction to <ACLASS="xref"HREF="ch06_01.htm"TITLE="Pattern Matching">Chapter 6</A>.</P><PRECLASS="programlisting">while (<>) { 1 while s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; print;}</PRE><PCLASS="para">If you're looking at the second <CODECLASS="literal">while</CODE> loop and wondering why it couldn't have been written as part of a simple <CODECLASS="literal">s///g</CODE> instead, it's because you need to recalculate the length from the start of the line again each time (stored in <CODECLASS="literal">$`</CODE>) rather than merely from where the last match occurred.</P><PCLASS="para">The obscure convention <CODECLASS="literal">1</CODE> <CODECLASS="literal">while</CODE> <ACLASS="indexterm"NAME="ch01-idx-1000011494-0"></A><CODECLASS="literal">CONDITION</CODE> is the same as <CODECLASS="literal">while</CODE> <CODECLASS="literal">(CONDITION)</CODE> <CODECLASS="literal">{</CODE> <CODECLASS="literal">}</CODE>, but shorter. Its origins date to when Perl ran the first incredibly faster than the second. While the second is now almost as fast, it remains convenient, and the habit has stuck.</P><PCLASS="para">The standard Text::Tabs module provides conversion functions to convert both directions, exports a <CODECLASS="literal">$tabstop</CODE> variable to control the number of spaces per tab, and does not incur the performance hit because it uses <CODECLASS="literal">$1</CODE> and <CODECLASS="literal">$2</CODE> rather than <CODECLASS="literal">$&</CODE> and <CODECLASS="literal">$`</CODE>.</P><PRECLASS="programlisting">use Text::Tabs;$tabstop = 4;while (<>) { print expand($_) }</PRE><PCLASS="para">We can also use Text::Tabs to "unexpand" the tabs. This example uses the default <CODECLASS="literal">$tabstop</CODE> value of 8:</P><PRECLASS="programlisting">use Text::Tabs;while (<>) { print unexpand($_) }</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-803">See Also</A></H3><PCLASS="para">The manpage for the Text::Tabs module (also in <ACLASS="olink"HREF="../prog/ch07_01.htm">Chapter 7</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A>); the <CODECLASS="literal">s///</CODE> operator in <EMCLASS="emphasis">perlre </EM>(1) and <EMCLASS="emphasis">perlop </EM>(1) and the <ACLASS="olink"HREF="../prog/ch02_04.htm">"Pattern Matching"</A> and <ACLASS="olink"HREF="../prog/ch02_04.htm#PERL2-CH-2-SECT-4.1">"Regular Expressions"</A> sections of <ACLASS="olink"HREF="../prog/ch02_01.htm">Chapter 2</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A><ACLASS="indexterm"NAME="ch01-idx-1000010244-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010244-1"></A><ACLASS="indexterm"NAME="ch01-idx-1000010244-2"></A><ACLASS="indexterm"NAME="ch01-idx-1000010244-3"></A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_07.htm"TITLE="1.6. Reversing a String by Word or Character"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 1.6. Reversing a String by Word or Character"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_09.htm"TITLE="1.8. Expanding Variables in User Input"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 1.8. Expanding Variables in User Input"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">1.6. Reversing a String by Word or Character</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">1.8. Expanding Variables in User Input</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <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 + -