ch04_19.htm
来自「By Tom Christiansen and Nathan Torkingto」· HTM 代码 · 共 417 行
HTM
417 行
<HTML><HEAD><TITLE>Recipe 4.18. Program: words (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:32:15Z"><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="ch04_01.htm"TITLE="4. Arrays"><LINKREL="prev"HREF="ch04_18.htm"TITLE="4.17. Randomizing an Array"><LINKREL="next"HREF="ch04_20.htm"TITLE="4.19. Program: permute"></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="ch04_18.htm"TITLE="4.17. Randomizing an Array"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 4.17. Randomizing an Array"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch04_01.htm"TITLE="4. Arrays"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch04_20.htm"TITLE="4.19. Program: permute"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 4.19. Program: permute"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch04-41630">4.18. Program: words</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch04-pgfId-1715">Description <ACLASS="indexterm"NAME="ch04-idx-1000006788-0"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-1"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-2"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-3"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-4"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-5"></A><ACLASS="indexterm"NAME="ch04-idx-1000006788-6"></A></A></H3><PCLASS="para">Have you ever wondered how programs like <EMCLASS="emphasis">ls</EM> generate columns of sorted output that you read down the columns instead of across the rows? For example:</P><PRECLASS="programlisting">awk cp ed login mount rmdir sumbasename csh egrep ls mt sed synccat date fgrep mail mv sh tarchgrp dd grep mkdir ps sort touchchmod df kill mknod pwd stty vichown echo ln more rm su</PRE><PCLASS="para"><ACLASS="xref"HREF="ch04_19.htm#ch04-10807"TITLE="words">Example 4.2</A> does this.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch04-10807">Example 4.2: words</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# words - gather lines, present in columnsuse strict;my ($item, $cols, $rows, $maxlen);my ($xpixel, $ypixel, $mask, @data);<CODECLASS="literal">getwinsize();</CODE># first gather up every line of input,# remembering the longest line length seen$maxlen = 1; while (<>) { my $mylen; s/\s+$//; $maxlen = $mylen if (($mylen = length) > $maxlen); push(@data, $_);}$maxlen += 1; # to make extra space# determine boundaries of screen$cols = int($cols / $maxlen) || 1;$rows = int(($#data+$cols) / $cols);# pre-create mask for faster computation$mask = sprintf("%%-%ds ", $maxlen-1);# subroutine to check whether at last item on linesub EOL { ($item+1) % $cols == 0 } # now process each item, picking out proper piece for this positionfor ($item = 0; $item < $rows * $cols; $item++) { my $target = ($item % $cols) * $rows + int($item/$cols); my $piece = sprintf($mask, $target < @data ? $data[$target] : ""); $piece =~ s/\s+$// if EOL(); # don't blank-pad to EOL print $piece; print "\n" if EOL();}# finish up if neededprint "\n" if EOL();# not portable -- linux onlysub getwinsize { my $winsize = "\0" x 8; my $TIOCGWINSZ = 0x40087468; if (ioctl(STDOUT, $TIOCGWINSZ, $winsize)) { ($rows, $cols, $xpixel, $ypixel) = unpack('S4', $winsize); } else { $cols = 80; }}</PRE></DIV><PCLASS="para">The most obvious way to print out a sorted list in columns is to print each element of the list, one at a time, padded out to a particular width. When you're about to hit the end of the line, generate a newline. But that only works if you're planning on reading each row left to right. If you instead expect to read it down each column, this approach won't do.</P><PCLASS="para">The <EMCLASS="emphasis">words</EM> program is a filter that generates output going down the columns. It reads all input, keeping track of the length of the longest line seen. Once everything has been read in, it divides the screen width by the length of the longest input record seen, yielding the expected number of columns.</P><PCLASS="para">Then the program goes into a loop that executes once per input record, but the output order isn't in the obvious order. Imagine you had a list of nine items:</P><PRECLASS="programlisting">Wrong Right----- -----1 2 3 1 4 74 5 6 2 5 87 8 9 3 6 9</PRE><PCLASS="para">The <EMCLASS="emphasis">words</EM> program does the necessary calculations to print out elements <CODECLASS="literal">(1,4,7)</CODE> on one line, <CODECLASS="literal">(2,5,8)</CODE> on the next, and <CODECLASS="literal">(3,6,9)</CODE> on the last.</P><PCLASS="para">To figure out the current window size, this program does an <CODECLASS="literal">ioctl</CODE> call. This works fine - on the system it was written for. On any other system, it won't work. If that's good enough for you, then good for you. <ACLASS="xref"HREF="ch12_15.htm"TITLE="Using h2ph to Translate C #include Files">Recipe 12.14</A> shows how to find this on your system using the <EMCLASS="emphasis">ioctl.ph</EM> file, or with a C program. <ACLASS="xref"HREF="ch15_05.htm"TITLE="Determining Terminal or Window Size">Recipe 15.4</A> shows a more portable solution, but that requires installing a CPAN module.<ACLASS="indexterm"NAME="ch04-idx-1000006790-0"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-1"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-2"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-3"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-4"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-5"></A><ACLASS="indexterm"NAME="ch04-idx-1000006790-6"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch04-pgfId-1000007207">See Also</A></H3><PCLASS="para"><ACLASS="xref"HREF="ch15_05.htm"TITLE="Determining Terminal or Window Size">Recipe 15.4</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="ch04_18.htm"TITLE="4.17. Randomizing an Array"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 4.17. Randomizing an Array"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="ch04_20.htm"TITLE="4.19. Program: permute"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 4.19. Program: permute"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">4.17. Randomizing an Array</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">4.19. Program: permute</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 + =
减小字号Ctrl + -
显示快捷键?