Perl On Win32
Perl On Win32
http://kickme.to/tiger/
By Randal L. Schwartz, Erik Olson & Tom Christiansen; ISBN 1-56592-324-3, 306 pages. First Edition, August 1997. (See the catalog page for this book.)
Index
Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X
Table of Contents
Foreword to the First Edition of Learning Perl Foreword to the Present Edition Preface Chapter 1: Introduction Chapter 2: Scalar Data Chapter 3: Arrays and List Data Chapter 4: Control Structures Chapter 5: Hashes Chapter 6: Basic I/O Chapter 7: Regular Expressions Chapter 8: Functions Chapter 9: Miscellaneous Control Structures Chapter 10: Filehandles and File Tests Chapter 11: Formats Chapter 12: Directory Access Chapter 13: File and Directory Manipulation Chapter 14: Process Management Chapter 15: Other Data Transformation Chapter 16: System Information Chapter 17: Database Manipulation Chapter 18: CGI Programming Chapter 19: OLE Automation Appendix A: Exercise Answers
Appendix B: Libraries and Modules Appendix C: Networking Clients Appendix D: Topics We Didn't Mention Examples
The Perl CD Bookshelf Navigation Copyright 1999 O'Reilly & Associates. All Rights Reserved.
Some computer scientists (the reductionists, in particular) would like to deny it, but people have funny-shaped minds. Mental geography is not linear, and cannot be mapped onto a flat surface without severe distortion. But for the last score years or so, computer reductionists have been first bowing down at the Temple of Orthogonality, then rising up to preach their ideas of ascetic rectitude to any who would listen. Their fervent but misguided desire was simply to squash your mind to fit their mindset, to smush your patterns of thought into some sort of Hyperdimensional Flatland. It's a joyless existence, being smushed. Nevertheless, your native common sense has shown through in spots. You and your conceptual ancestors have transcended the dreary landscape to compose many lovely computer incantations. (Some of which, at times, actually did what you wanted them to.) The most blessed of these incantations were canonized as Standards, because they managed to tap into something mystical and magical, performing the miracle of Doing What You Expect. What nobody noticed in all the excitement was that the computer reductionists were still busily trying to smush your minds flat, albeit on a slightly higher plane of existence. The decree, therefore, went out (I'm sure you've heard of it) that computer incantations were only allowed to perform one miracle apiece. "Do one thing and do it well" was the rallying cry, and with one stroke, shell programmers were condemned to a life of muttering and counting beads on strings (which in these latter days have come to be known as pipelines). This was when I made my small contribution to saving the world. I was rolling some of those very beads around in my fingers one day and pondering the hopelessness (and haplessness) of my existence, when it occurred to me that it might be interesting to melt down some of those mystical beads and see what would happen to their Magic if I made a single, slightly larger bead out of them. So I fired up the old Bunsen burner, picked out some of my favorite beads, and let them melt together however they would. And lo! the new Magic was more powerful than the sum of its parts and parcels. That's odd, thought I. Why should it be, that the Sedulous Bead of Regular Expressions, when bonded together with the Shellacious Bead of Gnostic Interpolation, and the Awkward Bead of Simple Data Typology, should produce more Magic, pound for pound, than they do when strung out on strings? I said to myself, could it be that the beads can exchange power with each other because they no longer have to commune with each other through that skinny little string? Could the pipeline be holding back the flow of information, much as wine doth resist flowing through the neck of Doctor von Neumann's famous bottle? This demanded (of me) more scrutiny (of it). So I melted that larger bead together with a few more of my favorite beads, and the same thing happened, only more so. It was practically a combinatorial explosion of potential incantations: the Basic Bead of Output Formats and the Lispery Bead of Dynamic Scoping bonded themselves with the C-rationalized Bead of Operators Galore, and together they put forth a brilliant pulse of power that spread to thousands of machines throughout the entire civilized world. That message cost the net hundreds if not thousands of dollars to send everywhere. Obviously I was either onto something, or on something. I then gathered my courage about me and showed my new magical bead to some of you, and you then began to give me your favorite beads to add in as well. The Magic grew yet more powerful, as yet more
synergy was imbued in the silly thing. It was as if the Computational Elementals summoned by each bead were cooperating on your behalf to solve your problems for you. Why the sudden peace on earth and good will toward mentality? Perhaps it was because the beads were your favorite beads? Perhaps it was because I'm just a good bead picker? Perhaps I just got lucky. Whatever, the magical bead eventually grew into this rather odd-looking Amulet you see before you today. See it glitter, almost like a pearl. That was another joke. Really! I assure you! Ah well. I was a freshman once too... The Amulet isn't exactly beautiful though - in fact, up close it still looks like a bunch of beads melted together. Well, all right, I admit it. It's downright ugly. But never mind that. It's the Magic that counts. Speaking of Magic, look who just walked in the door! My good buddy Merlyn, er, I should say, Professor Schwartz, is here just in the nick of time to begin telling you how to perform miracles with this little Amulet, if you're willing to learn the proper mysterious incantations. And you're in good hands - I must admit that there's no one better at muttering mysterious incantations than Professor Schwartz. Eh, Merlyn? Anyway, to sum up. What you'll need most is courage. It is not an easy path that you've set your foot upon. You're learning a new language - a language full of strange runes and ancient chants, some easy and some difficult, many of which sound familiar, and some of which don't. You may be tempted to become discouraged and quit. But think you upon this: consider how long it took you to learn your own native tongue. Was it worth it? I think so. And have you finished learning it? I think not. Then do not expect to learn all the mysteries of Perl in a moment, as though you were consuming a mere peanut, or an olive. Rather, think of it as though you were consuming, say, a banana. Consider how this works. You do not wait to enjoy the banana until after you have eaten the whole thing. No, of course not. You enjoy each bite as you take it. And each bite motivates you to take the next bite, and the next. So then, speaking now of the fruit of Merlyn's labors, I would urge you to enjoy this, um, course. The fruit course, of course. Ahem, that was a joke too. Ah well. Here then, Professor, I present to you your new class. They seem to have no sense of humor whatsoever, but I expect you'll manage somehow. Class, I present to you Professor Randal L. Schwartz, Doctor of Syntax, Wizard at Large, and of course, Just Another Perl Hacker. He has my blessings, just as you have my blessings. May you Learn Perl. May you do Good Magic with Perl. And above all, may you have Lots of Fun with Perl. So be it! So do it! Larry Wall September, 1993
Learning Perl on Win32 Systems Book Index Next: Foreword to the Present Edition
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Next: Preface
Next: Preface
Preface
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Preface
Preface
Contents: What This Book Is About We'd Like to Hear from You Conventions Exercises Acknowledgments for First Edition Acknowledgments for the Second Edition Acknowledgments for the Win32 Edition
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Preface
Next: Conventions
Conventions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Preface
Next: Exercises
Conventions
The following typographic conventions are used in this book: Italic is used for filenames and command names. It is also used to highlight comments in command examples, and to define new terms when they first appear in the text. Constant Width is used in examples to show the text that you enter literally, and in regular text to show operators, variables, and the output from commands or programs. Constant Bold is used in examples to show the user's actual input at the terminal. Constant Italic is used in examples to show variables for which a context-specific substitution should be made. The variable filename, for example, would be replaced by some actual filename. Footnotes are used to attach parenthetical notes which you should not read on your first reading of this book. Sometimes, lies are presented to simplify the discussion, and a footnote restores the lie to truth. Often, the material in the footnote will be advanced information that is not discussed anywhere else in the book.
Previous: We'd Like to Hear from You Learning Perl on Win32 Systems Book Index Next: Exercises
Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Previous: Conventions
Preface
Exercises
The exercises in this book are available electronically by FTP and FTPMAIL. Use FTP if you are directly on the Internet. Use FTPMAIL if you are not on the Internet but can send and receive electronic mail to Internet sites. (This includes CompuServe users.)
FTP
If you have an Internet connection (permanent or dialup), the easiest way to use FTP is via your web browser or favorite FTP client. To get the examples, simply point your browser to: ftp://ftp.oreilly.com/published/oreilly/nutshell/learning_perlnt/examples.zip If you don't have a web browser, you can use the command-line FTP client included with Windows NT (or Windows 95). % ftp ftp.oreilly.com Connected to ftp.oreilly.com. 220 ftp.oreilly.com FTP server (Version 6.34 Thu Oct 22 14:32:01 EDT 1992) ready. Name (ftp.oreilly.com:username): anonymous 331 Guest login ok, send e-mail address as password. Password: username@hostname Use your username and host here 230 Guest login ok, access restrictions apply. ftp> cd /published/oreilly/nutshell/learning_perlnt 250 CWD command successful. ftp> get README 200 PORT command successful. 150 Opening ASCII mode data connection for README (xxxx bytes). 226 Transfer complete. local: README remote: README xxxx bytes received in xxx seconds (xxx Kbytes/s) ftp> binary 200 Type set to I. ftp> get examples.zip 200 PORT command successful. 150 Opening BINARY mode data connection for examples.zip (xxxx bytes). 226 Transfer complete. local: exercises remote: exercises xxxx bytes received in xxx seconds (xxx Kbytes/s) ftp> quit 221 Goodbye. %
FTPMAIL
FTPMAIL is a mail server available to anyone who can send electronic mail to, and receive electronic mail from, Internet sites. Any company or service provider that allows email connections to the Internet can access FTPMAIL. You send mail to [email protected]. In the message body, give the FTP commands you want to run. The server will run anonymous FTP for you, and mail the files back to you. To get a complete help file, send a message with no subject and the single word "help" in the body. The following is an example mail message that gets the examples. This command sends you a listing of the files in the selected directory and the requested example files. The listing is useful if you are interested in a later version of the examples. Subject: reply-to username@hostname (Message Body) Where you want files mailed open cd /published/oreilly/nutshell/learning_perlnt dir get README mode binary uuencode get examples.zip quit . A signature at the end of the message is acceptable as long as it appears after "quit."
Previous: Conventions Learning Perl on Win32 Systems Book Index Next: Acknowledgments for First Edition
Conventions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Previous: Exercises
Preface
the way (especially suggesting the stroll at the end of the first chapter). His editorial criticisms were always right on, and his incessant talent for beating me over the head ever so gently allowed me to make this book a piece of art with which I'm extremely pleased. As always, a special thank you to both Lyle and Jack, for teaching me nearly everything I know about writing. And finally, an immeasurable thank you to my friend and partner, Larry Wall, for giving Perl to us all in the first place. A one L Randal wrote a book, A two L llama for the look, But to whom we owe it all Is the three L Larry Wall! Randal L. Schwartz
Previous: Exercises Learning Perl on Win32 Systems Book Index Next: Acknowledgments for the Second Edition
Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Preface
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Preface
Next: 1. Introduction
1. Introduction
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1
1. Introduction
Contents: History of Perl Purpose of Perl Availability Support Basic Concepts A Stroll Through Perl Exercises
seems to bind much of the Internet together. Perl is now used to create web pages, read Usenet news, do system adminstration and systems programming, write network clients and servers, and much more. The three chief virtues of a Perl programmer (indeed, of any programmer) are sometimes said to be laziness, impatience, and hubris. Although these may seem like undesirable qualities at first blush (just ask your SO), there's more to this than there appears to be. Laziness is the quality that makes you take great efforts to reduce the overall amount of work that you have to do. Lazy programmers are apt to develop reusable and general solutions that can be used in more than one place, and are more apt to document what they do, so that they don't have to ever waste time or torture their brains figuring it out again. Impatient programmers get angry whenever they have to do anything that the computer could be doing for them. Hence, they develop programs that anticipate their needs and solve problems for them, so that they can do less (there's that laziness again) while accomplishing more. Finally, hubris is that quality which makes programmers write programs that they want other people to see (and be able to maintain). Hubris is also a quality that promotes innovation: if you think that you have a better way and you're not afraid to prove it, you're often right. Odd ideas for a culture, perhaps, but effective ones. Here's another tenet of the Perl way: "There's more than one way to do it." What this means is that Perl programmers are a results-oriented lot. They're likely to applaud any tool that gets the job done, regardless of whether or not the code looks like something they would have written. Another side effect of this tenet that particularly endears itself to Win32 Perl programmers is that Perl is highly portable. Although ready-made scripts that you find on the Net may use existing UNIX tools or UNIX system calls that aren't portable to the Windows environment (this scenario has led Win32 programmers to say, "There's more than one way to do it, and it's a good thing, because most of the ways don't work"), you can nearly always find a way to make them work (and nobody will make fun of you if your solution is perhaps somewhat less than elegant). True to this philosophy, Perl stands for either Practical Extraction and Report Language or Pathologically Eclectic Rubbish Lister (both derivations are sanctioned by the Perl community). Perl for Win32 sprang into existence when Microsoft commissioned ActiveState Tool Corporation (formerly Hip Communications) to do a port for inclusion in the Windows NT Resource Kit. ActiveState is still improving Perl for Win32, extending it with functionality specific to the Win32 platforms, and incorporating the best and most appropriate new features as they are added to the core Perl distribution. You'll find that Perl for Win32 uses some of the coolest and most compelling technologies available to Windows programmers including OLE automation, ODBC database connectivity, ActiveX scripting, and much more. The source code for Perl (including Perl for Win32) is freely available and freely redistributable. If you want to extend Perl to provide additional features, or embed the interpreter in your own application, you can easily do so. You'll also find that the Perl community believes in (and practices) information and code sharing. There is an archive network (called the CPAN, for Comprehensive Perl Archive Network), where you can find thousands of existing Perl programs and code fragments. In addition to a vast body of high quality pre-written code, Perl excels at rapid application development. Part of this is due to the powerful qualities of language that let you do lots of work with a few
statements - another part is due to the Perl development tools themselves. Perl is an interpreted language, but it might work a little bit differently from other interpreted languages that you've used. Perl is actually both a compiler and an interpreter. When you invoke the Perl interpreter on a Perl script file, the file is first compiled and optimized, then efficiently executed. Not only does this allow for efficient runtime execution, it also promotes a quick development cycle, in which you can quickly make changes and rerun your script without going through a long compile and link cycle. In spite of Perl's relatively free syntax, you can easily develop correct Perl programs. Not only is there a Perl debugger, but the compiler itself will issue informative warnings when you're treading on thin ice. Furthermore, the interpreter doesn't execute unless the program compiles completely. This feature saves you from the common interpreted-language nightmare in which the first half of your program works and does something to a file, and then the second half doesn't.
Previous: Acknowledgments for the Win32 Edition Learning Perl on Win32 Systems Book Index Next: 1.2 Purpose of Perl
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
1.3 Availability
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
1.3 Availability
Unless you have had the good fortune of having a system administrator install Perl on your workstation, you will need to obtain and install a copy yourself. Perl is distributed under the GNU Public License,[1] which says something like, "you can distribute binaries of Perl only if you make the source code available at no cost, and if you modify Perl, you have to distribute the source to your modifications as well." And that's essentially free. You can get the source to Perl for the cost of a few megabytes over a wire. [1] Or the slightly more liberal Artistic License, found in the distribution sources. At the time of this writing, there are two Perl distributions that run on Windows NT and Windows 95. There is the ActiveState port of Perl, called Perl for Win32, and starting with Perl 5.004, the standard Perl distribution includes support for Win32 systems. The two versions are largely compatible, with some of the Perl 5.004 code being based on the ActiveState port, but there are some differences. The programs and examples presented in this tutorial have been tested on both systems; when a distribution requires different code, we point that fact out. The architects of both distibutions have announced their intention to merge the distributions, but they have not yet announced a time frame for that to happen.
You can choose from one of several different binary distributions: there's a standalone version of the Perl interpreter (Perl for Win32), a version for use as an ISAPI[3] extension with ISAPI compliant Web servers (PerlIS), and an ActiveX scripting version (PerlScript). If you choose either the ISAPI or the PerlScript version, you will still need the standalone version of the interpreter, because it contains the Perl libraries, documentation, and example files. Binary distributions exist for both DEC Alpha and Intel versions of Windows NT. At the time of this writing, the current release version of Perl for Win32 is based on Perl 5.003, and the build number is 306. [3] For more on ISAPI and PerlIS, see Chapter 18, CGI Programming. The standalone version of Perl for Win32 is easy to install; the distribution comes as a self-extracting executable. Just run the executable, select the directory to install into, and run the installation script as prompted by the installer. You'll probably need to re-logon (in Windows NT) or reboot (in Windows 95) to your workstation because the installation changes the PATH environment variable. The Perl for Win32 distribution includes the Perl interpreter, the standard Perl libraries (useful collections of code that aren't part of the core language), and a number of Win32 extension modules. The Win32 extension modules either extend Perl to provide additional functionality for Win32 platforms or they provide functionality that is present in UNIX versions of Perl, but which is unimplemented or otherwise missing in Win32 versions. The distribution also includes help documentation (in HTML format) and example scripts that demonstrate the various features of Perl and the Win32 extensions. Currently, if you're interested in either the ISAPI version of Perl, or PerlScript, you need to get the ActiveState distribution, because neither of these tools works with the standard distribution. Also, if you don't have convenient access to either the Microsoft or Borland C++ compilers, you'll definitely want to grab the binary ActiveState distibution.
Assuming you're using gzip and tar, execute the following (you might need to adjust the filename): > gzip -dc perl5.004_01.tar.gz | tar xf If you're using WinZip or some other utility, make sure that you preserve the directory structure. Next, edit the makefile (Makefile) in the win32 subdirectory of the distribution and make sure that you're happy with the values for the install drive and directory. Then, execute the following commands from the win32 subdirectory of the distribution to build, test, and install the distribution. This assumes that you have the proper environment variables (LIB, INCLUDE, etc) set up for your compiler (this assumes nmake is your make utility). > nmake (Build all of Perl) > nmake test (Test your distribution) > nmake install (Install to the target dir. in the Makefile) Assuming everything is built correctly, you just need to add the bin subdirectory of the installation target directory to your path. For example, if you installed the Perl distribution to c:\Perl, you'll want to add c:\Perl\bin to your path. Finally, restart your machine to get the environment changes, and you're ready to go. We strongly recommend getting the libwin32 package from CPAN, and installing it as well. We'll be discussing several of the extensions provided by libwin32 throughout this book (the ActiveState distribution includes most of these extensions already). Installation of libwin32 is easy. Simply download and extract the file, and then execute the following commands from the directory to which you extracted the files: > perl Makefile.PL > nmake > nmake test > nmake install
1.4 Support
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
1.4 Support
Perl is the child of Larry Wall, and is still being coddled by him. Bug reports and requests for enhancements generally get fixed in later releases, but he is under no obligation to do anything with them. Nevertheless, Larry really does enjoy hearing from all of us, and does truly like to see Perl be useful to the world at large. Direct email generally gets a response (even if it is merely his email answering machine), and sometimes a personal response. These days, Larry is actually acting as an architect to the "Perl 5 Porters" group, a bunch of very clever people that have had a lot to do with the last few Perl releases. If Larry got hit by a bus, everyone would be very sad for a long time, but Perl would still continue to mature under the direction of this group. You will probably find that your best bet for support comes from the global online Perl community, accessible via the Usenet newsgroup comp.lang.perl.misc. If you are emailable to the Internet, but not amenable to Usenet, you can also wire yourself into this group by sending a request to [email protected], which will reach a human who can connect you to a two-way email gateway into the group, and give you guidelines on how the group works. When you subscribe to the newsgroup, you'll find roughly 50 to 200 postings a day (at the time of this writing) on all manner of subjects from beginner questions to complicated porting issues and interface problems, and even a fairly large program or two. The newsgroup is almost constantly monitored by many Perl experts. Most of the time, your question gets answered within minutes of your news article reaching a major Usenet hub. Just try getting that level of support from your favorite software vendor for free! Larry himself reads the group as time permits, and has been known to interject authoritative articles to end bickering or clarify a point. After all, without Usenet, there probably wouldn't have been a place to easily announce Perl to the world. In addition to the newsgroup, you should also be reading the Perl documentation which comes with the Perl distribution. Another authoritative source is the Programming Perl Nutshell Handbook, by Larry Wall, Tom Christiansen, and Randal L. Schwartz (O'Reilly & Associates, 1996). Programming Perl is known as "The Camel Book" because of the animal on its cover. The Camel Book contains the complete reference information, some tutorial stuff, and a bunch of miscellaneous information about Perl in a nicely bound form. The Frequently Asked Questions (FAQ) list for Perl is a great source of answers for common questions that arise about Perl. The FAQ is available in the perlfaq documentation page as of the 5.004 release of Perl, is posted periodically to the moderated comp.lang.perl.announce newsgroup, and can also be found
on any CPAN mirror under the doc/FAQs directory. Finally, for specific issues concerning Perl for Win32, a trio of mailing lists is available: Perl-Win32-Users, Perl-Win32-Porters, and Perl-Win32-Announce. Perl-Win32-Users[4] is for general questions on installation and usage. This list has moderate traffic at times and can be a valuable resource for Perl-for-Win32 users. The Perl-Win32-Porters list is for development and porting issues only. Please do not ask installation or usage questions of this list. The Perl-Win32-Announce list is for announcements of new builds, bugs, or issues, and is a read-only list. The traffic is very light, and if you're serious about Perl for Win32, you probably want to subscribe to this list. [4] This list has a history of down time. If it seems to be down for a few days, try resubscribing or wait a while. It usually starts working again. To subscribe to any of the Perl-for-Win32 lists, send a message to [email protected] with the message SUBSCRIBE Perl-Win32-Users (or whichever list you're interested in) in the body of the message. Even though the Perl community is largely a helpful and collaborative group, they do expect you to do your homework before asking questions. You should always search the applicable FAQs before posting your question to the Usenet or a mailing list. You can find the Perl-for-Win32 FAQ at http://www.endcontsw.com/people/evangelo/Perl_for_Win32_FAQ.html, or by searching around at the ActiveState site (http://www.activestate.com). You can find the general Perl FAQs at any CPAN site (try the /doc/FAQs) directory.
Previous: 1.3 Availability Learning Perl on Win32 Systems Book Index Next: 1.5 Basic Concepts
1.3 Availability
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
[6] This statement is not true if you're using Windows 95, in which case you'll have to do the whole thing manually. From an Explorer window, go to View/Options/File Types and add a new type with the .pl extension and the path to the Perl interpreter. > assoc .plx=Perl > ftype Perl=c:\myperl\bin\perl.exe %1 %* If you can't bear the thought of typing the extension every time you execute a Perl script, you can set the PATHEXT environment variable so that it includes Perl scripts. For example: > set PATHEXT=%PATHEXT%;.PLX This setting will let you type > myscript without including the file extension. Take care when setting PATHEXT permanently - it also includes executable file types like .COM, .EXE, .BAT, and .CMD. If you inadvertently lose those extensions, you'll have difficulty invoking applications and script files. Perl is mostly a free-format language like C - whitespace between tokens (elements of the program, like print or +) is optional, unless two tokens placed together can be mistaken for another token, in which case whitespace of some kind is mandatory. (Whitespace consists of spaces, tabs, newlines, returns, or formfeeds.) A few constructs require a certain kind of whitespace in a certain place, but they'll be pointed out when we get to them. You can assume that the kind and amount of whitespace between tokens is otherwise arbitrary. Although many interesting Perl programs can be written on one line, typically a Perl program is indented much like a C program, with nested parts of statements indented more than the surrounding parts. You'll see plenty of examples showing a typical indentation style throughout this book. Just like a batch file, a Perl program consists of all of the Perl statements of the file taken collectively as one big routine to execute. Perl has no concept of a "main" routine as in C. Perl comments are single-line comments (like REM in a batch file or // in a C++ or Java file). Anything from an unquoted pound sign (#) to the end-of-line is a comment. There are no C-like multiline comments. Unlike the command shell, the Perl interpreter completely parses and compiles the program before executing any of it. This means that you can never get a syntax error from a program once the program has started, and that the whitespace and comments simply disappear and won't slow the program down. In fact, this compilation phase ensures the rapid execution of Perl operations once execution starts, and provides additional motivation for dropping C as a systems utility language merely on the grounds that C is compiled. This compilation does take time - it's inefficient to have a voluminous Perl program that does one small quick task (out of many potential tasks) and then exits, because the run-time for the program will be dwarfed by the compile time. So, Perl is like a compiler and an interpreter. It's a compiler because the program is completely read and parsed before the first statement is executed. It's an interpreter because no object code sits around filling
up disk space. In some ways, it's the best of both worlds. Admittedly, a caching of the compiled object code between invocations, or even translation into native machine code, would be nice. A working version of such a compiler already exists, and is currently scheduled to be bundled into the 5.005 release. See the Perl FAQ for the current status.
1.5.1 Documentation
Throughout this book, we'll refer to the documentation included with the Perl distributions. The ActiveState port comes with documentation in HTML format; you can find it in the /docs subdirectory of the distribution. When we refer to the documentation, we'll just refer to the base name of the file without the extension. For example, if we refer to perlfunc, we really mean /docs/Perl/perlfunc.html. Win32 specific documentation is located in the /docs/Perl-Win32 subdirectory, so a reference to win32ext really refers to /docs/Perl-Win32/win32ext.html. If you have the standard 5.004 distribution, you can use the perldoc command from the command line. perldoc is a batch file wrapper around a Perl script, found in the /bin directory of the distribution. perldoc lets you view documentation pages or module documentation by invoking it as follows: > perldoc perlfunc perldoc extracts the documentation from the Perl POD (plain old documentation) format found in the /pod subdirectory of the distribution. If all else fails, you can just read the pod files with your favorite text editor.
Previous: 1.4 Support Learning Perl on Win32 Systems Book Index Next: 1.6 A Stroll Through Perl
1.4 Support
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
The eq operator compares two strings. If they are equal (character for character, and of the same length), the result is true. (No comparable operator[8] exists in C or C++.) [8] Well, OK, there's a standard C library function. But that's not an operator. The if statement selects which block of statements (between matching curly braces) is executed - if the expression is true, it's the first block, otherwise it's the second block.
the day of the week. A better solution is to store all of the possible answers in a data structure called a list, or (preferrably) an array. Each element of the array is a separate scalar variable that can be independently set or accessed. The entire array can also be given a value in one fell swoop. We can assign a value to the entire array named @words so that it contains three possible good passwords: @words = ("camel","gecko","alpaca"); Array variable names begin with @, so they are distinct from scalar variable names. Another way to write this so that we don't have to put all those quotemarks there is with the qw() syntax, like so: @words = qw(camel gecko alpaca); These mean exactly the same thing; the qw makes it as if we had quoted each of three strings. After the array is assigned, we can access each element by using a subscript reference (subscripts start at zero). So, $words[0] is camel, $words[1] is gecko, and $words[2] is alpaca. The subscript can be an expression as well, so if we set $i to 2, then $words[$i] is alpaca. (Subscript references start with $ rather than @, because they refer to a single element of the array rather than the whole array.) Going back to our previous example: @words = qw(camel gecko alpaca); print "What is your name? "; $name = <STDIN>; chomp $name; if ($name eq "Erik") { print "Hello, Erik! How good of you to be here!\n"; } else { print "Hello, $name!\n"; # ordinary greeting print "What is the secret word? "; $guess = <STDIN>; chomp ($guess); $i = 0; # try this word first $correct = "maybe"; # is the guess correct or not? while ($correct eq "maybe") { # keep checking til we know if ($words[$i] eq $guess) { # right? $correct = "yes"; # yes! } elsif ($i < 2) { # more words to look at? $i = $i + 1; # look at the next word next time } else { # no more words, must be bad print "Wrong, try again. What is the secret word?"; $guess = <STDIN>; chomp ($guess); $i = 0; # start checking at the first word again } } # end of while not correct } # end of "not Erik" You'll notice we're using the scalar variable $correct to indicate that we are either still looking for a
good password, or that we've found one. This program also shows the elsif block of the if-then-else statement. This exact construct is not present in all programming languages - it's an abbreviation of the else block together with a new if condition, but it does not nest inside yet another pair of curly braces. It's a very Perl-like thing to compare a set of conditions in a cascaded if-elsif-elsif-elsif-else chain. Perl doesn't really have the equivalent of C's switch or Pascal's case statement, although you can build one yourself without too much trouble. See Chapter 2 of Programming Perl or the perlsyn documentation for details.
Table 1.1: Matching Persons to Secret Words Person Secret Word Fred camel
Wilma alpaca Notice that both Betty and Wilma have the same secret word. This is fine. The easiest way to store such a table in Perl is with a hash. Each element of the hash holds a separate scalar value (just like the other type of array), but each hash is referenced by a key, which can be any scalar value (any string or number, including noninteger and negative values). To create a hash called %words (notice the use of %, rather than @) with the keys and values given in Table 1.1, we assign a value to %words (much as we did earlier with the array): %words = qw( fred camel barney gecko betty alpaca wilma alpaca ); Each pair of values in the list represents one key and its corresponding value in the hash. Note that we broke this assignment over many lines without any sort of line continuation character. We could do so because whitespace is generally insignificant in a Perl program. To find the secret word for Betty, we need to use Betty as the key in a reference to the hash %words, via some expression such as $words{"betty"}. The value of this reference is alpaca, similar to what
we had before with the other array. Also, as before, the key can be any expression, so setting $person to betty and evaluating $words{$person} gives alpaca as well. Putting all this together, we get a program like this: %words = qw( fred camel barney gecko betty alpaca wilma alpaca ); print "What is your name? "; $name = <STDIN>; chomp ($name); if ($name eq "Erik") { print "Hello, Erik! How good of you to be here!\n"; } else { print "Hello, $name!\n"; # ordinary greeting $secretword = $words{$name}; # get the secret word print "What is the secret word? "; $guess = <STDIN>; chomp ($guess); while ($guess ne $secretword) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess); } } Note the lookup of the secret word. If the name is not found, the value of $secretword will be an empty string,[9] which we can then check for if we want to define a default secret word for everyone else. Here's how that process looks: [9] Well, OK, the value is really the undef value, but it looks like an empty string to the eq operator. You'd get a warning about this value if you used -w on the command line, which is why we omitted it here. [... rest of program deleted ...] $secretword = $words{$name}; # get the secret word if ($secretword eq "") { # oops, not found $secretword = "groucho"; # sure, why a duck? } print "What is the secret word? "; [... rest of program deleted ...]
while ($guess ne $secretword) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess); } } As you can see, the program is a far cry from the simple Hello world, but it's still very small and workable, and does quite a bit for being so short. This is The Perl Way. Perl provides nearly every regular expression feature imaginable. In addition, the way Perl handles string matching is about the fastest on the planet, so you don't lose performance. String matching in Perl often compares favorably to hand-coded C programs written specifically for the same purpose.
[11] Experts will note that we could have also constructed something like s/(\S*).*/\L$1/ to do this processing in one fell swoop, but experts probably won't be reading this section. Putting everything together results in the following: %words = qw( fred camel barney gecko betty alpaca wilma alpaca ); print "What is your name? "; $name = <STDIN>; chomp ($name); $original_name = $name; #save for greeting $name =~ s/\W.*//; # get rid of everything after first word $name =~ tr/A-Z/a-z/; # lowercase everything if ($name eq "erik") { # ok to compare this way now print "Hello, Erik! How good of you to be here!\n"; } else { print "Hello, $original_name!\n"; # ordinary greeting $secretword = $words{$name}; # get the secret word if ($secretword eq "") { # oops, not found $secretword = "groucho"; # sure, why a duck? } print "What is the secret word? "; $guess = <STDIN>; chomp ($guess); while ($guess ne $secretword) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess); } } Notice how the regular expression match for Erik became a simple comparison again. After all, both Erik Olson and Erik become erik after the substitution and translation. And everyone else gets a fair ride, because Fred and Fred Flintstone both become fred, Barney Rubble and Barney, the little guy become barney, and so on. With just a few statements, we've made the program much more user friendly. You'll find that expressing complicated string manipulation with a few keystrokes is one of Perl's many strong points. However, hacking away at the name so that we could compare it and look it up in the table destroyed the name that was entered. So, before the program hacks on the name, it saves it in $original_name. (Like C symbols, Perl variable names consist of letters, digits, and underscores and can be of nearly
unlimited length.) We can then make references to $original_name later. Perl has many ways to monitor and mangle strings. You'll find out about most of them in Chapter 7, Regular Expressions, and Chapter 15, Other Data Transformation.
supplied value. In the absence of an explicit return statement, the last expression evaluated in a subroutine is the return value. We'll see how the return value is used after we finish describing the subroutine definition. The test for the elsif part looks a little complicated - let's break it apart: ($words{$somename} || "groucho") eq $someguess The first thing inside the parentheses is our familiar hash lookup, yielding some value from %words based on a key of $somename. The operator between that value and the string groucho is the || (logical-or) operator similar to that used in C. If the lookup from the hash has a value (meaning that the key $somename was in the hash), the value of the expression is that value. If the key could not be found, the string groucho is used instead. This step is a very Perl-like thing to do - specify some expression, and then provide a default value using || in case the expression turns out to be false. In any case, whether it's a value from the hash, or the default value groucho, we compare it to whatever was guessed. If the comparison is true, we return 1; otherwise, we return 0. So, expressed as a rule, if the name is erik, or the guess matches the lookup in %words based on the name (with a default of groucho if not found), then the subroutine returns 1; otherwise, it returns 0. Now, let's integrate all these additions with the rest of the program: %words = qw( fred camel barney gecko betty alpaca wilma alpaca ); print "What is your name? "; $name = <STDIN>; chomp ($name); if ($name =~ /^erik\b/i) { # back to the other way :-) print "Hello, Erik! How good of you to be here!\n"; } else { print "Hello, $name!\n"; # ordinary greeting print "What is the secret word? "; $guess = <STDIN>; chomp ($guess); while (! good_word($name,$guess)) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp $guess; } } [... insert definition of good_word() here ...] Notice that we've gone back to the regular expression to check for Erik, because now the main program does not have to pull apart the first name and convert it to lowercase.
The big difference is the while loop containing good_word. Here, we see an invocation of the subroutine passing two parameters, $name and $guess. Within the subroutine, the value of $somename is set from the first parameter, in this case $name. Likewise, $someguess is set from the second parameter, $guess. The value returned by the subroutine (either 1 or 0, recalling the definition given earlier) is logically inverted with the prefix ! (logical not) operator. As in C, this operator returns true if the expression following is false, and vice versa. The result of this negation controls the while loop. You can read this as "while it's not a good word..." Many well-written Perl programs read very much like English, provided you take a few liberties with either Perl or English. (But you certainly won't win a Pulitzer that way.) Note that the subroutine assumes that the value of the %words hash is set by the main program. Such a cavalier approach to global variables doesn't scale very well, of course. Generally speaking, variables not created with my are global to the whole program, while those my creates last only until the block in which they were declared exits. Don't worry; Perl does in fact support a rich variety of other kinds of variables, including those private to a file (or package), as well as variables private to a function that retain their values between invocations (which is what we could really use here). However, at this stage in your Perl education, explaining these variables would only complicate your life. When you're ready for such information, check out what Programming Perl has to say about scoping, subroutines, modules, and objects. Or, see the online documentation in the perlsub , perlmod , perlobj , and perltoot documentation.
} We're putting this code into a subroutine so that we can keep the main part of the program uncluttered. This organization also means that at a later time (hint: after a few more revisions in this stroll), we can change where the word list is stored, or even the format of the list. The arbitrarily chosen format of the word list is one item per line, with names and words alternating. So, for our current database, we'd have something like this: fred camel barney gecko betty alpaca wilma alpaca The open function creates a filehandle named WORDSLIST by associating it with a file named wordslist in the current directory. Note that the filehandle doesn't have a funny character in front of it as do the three variable types. Also, filehandles are generally uppercase - although they aren't required to be - for reasons detailed later. The while loop reads lines from the wordslist file (via the WORDSLIST filehandle) one line at a time. Each line is stored into the $name variable. When end-of-file is reached, the value returned by the <WORDSLIST> operation is the empty string,[12] which looks false to the while loop, and terminates it. That's how we get out at the end. [12] Well, technically the value is undef again, but empty string is close enough for this discussion. If you were running with the -w option, you would have to check that the return value read in was actually defined. The empty string returned by the <WORDSLIST> operation isn't merely empty - it's undef again. The defined function is how you test for undef when this matters. In the case of reading lines from a file, you'd test as shown: while ( defined ($name = <WORDSLIST>) ) { But if you were being that careful, you'd probably also have checked to make sure that open returned a true value. You know, that's probably not a bad idea either. The built-in die function is frequently used to exit the program with an error message in case something goes wrong. We'll see an example of this function in the next revision of the program. On the other hand, the normal case is that we've read a line (including the newline) into $name. First, off comes the newline using the chomp function. Then, we have to read the next line to get the secret word, holding it in the $word variable. This variable also gets the newline hacked off. The final line of the while loop puts $word into %words with a key of $name, so that the rest of the program can access it later. After the file has been read, the filehandle can be recycled with the close function. (Filehandles are
automatically closed anyway when the program exits, but we're trying to be tidy. If we were really tidy, we'd even check for a true return value from close in case the disk partition which held the file went south, its network filesystem became unreachable, or a similar catastrophe occurred. Yes, these things really do happen. Murphy will always be with us.) This subroutine definition can go after or before the other one. And, we invoke the subroutine instead of setting %words in the beginning of the program. Therefore, you could wrap up all of this as follows: init_words(); print "What is your name? "; $name = <STDIN>; chomp ($name); if ($name =~ /^erik\b/i) { # back to the other way :-) print "Hello, Erik! How good of you to be here!\n"; } else { print "Hello, $name!\n"; # ordinary greeting print "What is the secret word? "; $guess = <STDIN>; chomp ($guess); while (! good_word($name,$guess)) { print "Wrong, try again. What is the secret word? "; $guess = <STDIN>; chomp ($guess); } } ## subroutines from here down sub init_words { open (WORDSLIST,"wordslist") || die "can't open wordlist:$!"; while (defined ($name = <WORDSLIST>)) { chomp ($name); $word = <WORDSLIST>; chomp ($word); $words{$name} = $word; } close (WORDSLIST); } sub good_word { my($somename,$someguess) = @_; # name the parameters $somename =~ s/\W.*//; # delete everything after first word $somename =~ tr/A-Z/a-z/; # lowercase everything if ($somename eq "erik") { # should not need to guess return 1; # return value is true } elsif (($words{$somename} || "groucho") eq $someguess) { return 1; # return value is true } else { return 0; # return value is false
} } Now our program is starting to look full-grown. Notice the first executable line is an invocation of init_words(). The return value is not used in a further calculation, which is good because we didn't return anything remarkable. In this case, a true value is guaranteed (the value 1, in particular), because if the close had failed, the die would have printed a message to our STDERR error and exited the program. The die function is fully explained in Chapter 10, Filehandles and File Tests, but because the return values of anything that might fail must be checked, we'll get into the habit of using the function right from the start. The $! variable (also explained in Chapter 10) contains the system error message explaining why the system call failed. The open function is also used to open files for output, or open programs as files (demonstrated shortly). The full scoop on open comes much later in this book, however, in Chapter 10.
This method leaves you with a list (@files) of all filenames in the current directory that contain the .sec pattern. We'll provide more information on this later. So, if the current directory contains fred.sec and barney.sec, then $filename is barney.sec on the first pass through the while loop (the names come out in alphabetically sorted order). On the second pass, $filename is fred.sec. And there is no third pass because the glob returns an empty string the third time it is called, perceived by the while loop to be a false, causing an exit from the subroutine. Within the while loop, we open the file and verify that it is recent enough (less than seven days since the last modification). For the recent-enough files, we scan through as before. Note that if there are no files that match *.sec and are less than seven days old, the subroutine will exit without having set any secret words into the %words array. In such a case, everyone must use the word groucho. Oh well. (For real code, we would have added some check on the number of entries in %words before returning, and die'd if the check wasn't good. See the keys function when we get to hashes in Chapter 5, Hashes.)
The format definition begins with format STDOUT =, and ends with a single period. The other two lines comprise the format itself. The first line of this format is a field definition line that specifies the number, length, and type of the fields. For this format, we have three fields. The line following a field definition line is always a field value line. The value line gives a list of expressions that will be evaluated when this format is used, and the results of those expressions will be plugged into the fields defined in the previous line. We invoke this format with the write function, as shown: while ( defined($filename = glob("*.sec")) ) open (WORDSLIST, $filename) || die "can't open $filename: $!"; if (-M WORDSLIST <= 7.0) { while (defined ($name = <WORDSLIST>) chomp ($name); $word = <WORDSLIST>; chomp ($word); write; # invoke format STDOUT to } } close (WORDSLIST) || die "couldn't close } format STDOUT = @<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<< $filename, $name, $word . {
STDOUT
$filename: $!";
When the format is invoked, Perl evaluates the field expressions and generates a line that it sends to the STDOUT filehandle. Because write is invoked once each time through the loop, we'll get a series of lines with text in columns, one line for each secret word entry. Hmm. We haven't labeled the columns. That's easy enough. We just need to add a top-of-page format, as shown: format STDOUT_TOP = Page @<< $% Filename Name Word ================ ========== ============ . This format is named STDOUT_TOP, and will be used initially at the first invocation of the STDOUT format, and again every time 60 lines of output to STDOUT have been generated. These column headings line up with the columns from the STDOUT format, so everything comes out tidy. The first line of this format shows some constant text (Page) along with a three-character field definition. The following line is a field value line, which in this case has one expression. This expression is the $% variable,[19] which holds the number of pages printed - a very useful value in top-of-page
formats. [19] More mnemonic aliases for these predefined scalar variables are available via the English module, which provides English names for Perl's special variables. The third line of the format is blank. Because this line does not contain any fields, the line following it is not a field value line. This blank line is copied directly to the output, creating a blank line between the page number and the column headers below. The last two lines of the format also contain no fields, so they are copied as-is, directly to the output. So this format generates four lines, one of which has a part that changes from page to page. Just tack this definition onto the previous program to get it to work. Perl notices the top-of-page format automatically. Perl also has fields that are centered or right justified, and supports a filled paragraph area as well. More on these features when we get to formats in Chapter 11, Formats.
} Notice the new else part of the file age check. If the file is older than seven days, it gets renamed with the rename function. This function takes two parameters, renaming the file named by the first parameter to the name given in the second parameter. Perl has a complete range of file manipulation operators - nearly anything you can do to a file from a C program, you can also do from Perl.
hidden or a system file. We'll discuss file permissions and attributes in detail in Chapter 13. For now, just trust us that you want to use 0666 for creating DBM files. The second statement shows that we use this mapped hash just like a normal hash. However, creating or updating an element of the hash automatically updates the disk files that form the DBM. And, when the hash is later accessed, the values within the hash come directly from the disk image. This gives the hash a life beyond the current invocation of the program - a persistence of its own. The third statement disconnects the hash from the DBM, much like a file close operation. You can insert these three statements just ahead of the subroutine definitions. Although the inserted statements maintain the database adequately (and even create the database initially), we don't have any way of examining the information yet. To do so, we can create a separate little program that looks something like this: dbmopen (%last_good,"lastdb",0666) || die "can't dbmopen lastdb: $!"; foreach $name (sort keys %last_good) { $when = $last_good{$name}; $hours = (time - $when) / 3600; # compute hours ago write; } format STDOUT = User @<<<<<<<<<<<: last correct guess was @<<< hours ago. $name, $hours . We've got a few new operations here: a foreach loop, sorting a list, and getting the keys of an hash. First, the keys function takes a hash name as an argument and returns a list of all the keys of that hash in some unspecified order. For the %words hash defined earlier, the result is something like fred, barney, betty, wilma, in some unspecified order. For the %last_good hash, the result will be a list of all users who have guessed their own secret word successfully. The sort function sorts the list alphabetically (just like passing a text file through the sort command). This function makes sure that the list processed by the foreach statement is always in alphabetical order. The Perl foreach statement takes a list of values and assigns each one in turn to a scalar variable (here, $name), executing the body of the loop (a block) once for each value. So, for five names in the %last_good list, we get five passes through the loop, with $name being a different value each time. The body of the foreach loop loads up a couple of variables used within the STDOUT format, and then invokes the format. Note that we figure out the age of the entry by subtracting the stored system time (in the array) from the current time (as returned by time), and then divide that by 3600 (to convert seconds to hours). Perl also provides easy ways to create and maintain text-oriented databases and fixed-length-record
rename ($filename,"$filename.old") || die "can't rename $filename: $!"; } } } sub good_word { my($somename,$someguess) = @_; # name the parameters $somename =~ s/\W.*//; # delete everything after first word $somename =~ tr/A-Z/a-z/; # lowercase everything if ($somename eq "erik") { # should not need to guess return 1; # return value is true } elsif (($words{$somename} || "groucho") eq $someguess) { return 1; # return value is true } else { log_failure($somename,$someguess); return 0; # return value is false } } sub log_failure { my($somename,$someguess) = @_; # name the parameters open(LOG, ">>failures.log") || die "failures.log: $!"; print LOG "bad news: $somename guessed $someguess\n"; close (LOG) || die "can't close failures.log: $!"; } Next, we have the secret word lister: while ( defined($filename = glob("*.sec")) ) { open (WORDSLIST, $filename) || die "can't open $filename: $!"; if (-M WORDSLIST <= 7.0) { while (defined ($name = <WORDSLIST>)) { chomp ($name); $word = <WORDSLIST>; chomp ($word); write; # invoke format STDOUT to STDOUT } } close (WORDSLIST) || die "can't close $filename: $!"; } format STDOUT = @<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<< $filename, $name, $word . format STDOUT_TOP =
Page @<< $% Filename Name Word ================ ========== ============ . And finally, the last-time-a-word-was-used display program: dbmopen (%last_good,"lastdb",0666) || die "can't dbmopen lastdb: $!"; foreach $name (sort keys %last_good) { $when = $last_good{$name}; $hours = (time - $when) / 3600; # compute hours ago write; } dbmclose(%last_good) || die "can't dbmclose lastdb: $!"; format STDOUT = User @<<<<<<<<<<<: last correct guess was @<<< hours ago. $name, $hours . Together with the secret word lists (files named something.sec in the current directory) and the database, lastdb.dir and lastdb.pag, you'll have all you need.
Previous: 1.5 Basic Concepts Learning Perl on Win32 Systems Book Index Next: 1.7 Exercises
1.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 1 Introduction
1.7 Exercises
Normally, each chapter will end with some exercises, for which answers will be found in Appendix A, Exercise Answers. For this stroll, the answers have already been given above. 1. Type in the example programs, and get them to work. (You'll need to create the secret word lists as well.) Consult your local Perl guru if you need assistance.
Previous: 1.6 A Stroll Through Perl Learning Perl on Win32 Systems Book Index Next: 2. Scalar Data
2. Scalar Data
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 2
2. Scalar Data
Contents: What Is Scalar Data? Numbers Strings Scalar Operators Scalar Variables Scalar Operators and Functions <STDIN> as a Scalar Value Output with print The Undefined Value Exercises
1.7 Exercises
2.2 Numbers
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
2.2 Numbers
Although a scalar is either a number or a string,[1] consider numbers and strings separately for the moment. Numbers first, strings in a minute... [1] A scalar can also be a reference, but that is an advanced topic.
-1.2E-23
2.3 Strings
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
2.3 Strings
Strings are sequences of characters (like hello). Each character is an 8-bit value from the entire 256-character set (there's nothing special about the NUL character, as in some languages). The shortest possible string has no characters. The longest string fills all of your available memory (although you wouldn't be able to do much with that). This is in accordance with the principle of "no built-in limits" that Perl follows at every opportunity. Typical strings are printable sequences of letters, digits, and punctuation in the ASCII 32 to ASCII 126 range. However, the ability to have any character from 0 to 255 in a string means that you can create, scan, and manipulate raw binary data as strings - a task with which most other utilities would have great difficulty. (For example, you can patch your operating system by reading it into a Perl string, making the change, and writing the result back out.) Like numbers, strings have a literal representation (the way you represent the string in a Perl program). Literal strings come in two different flavors: single-quoted strings and double-quoted strings.[5] Another form that looks rather like these two is the back-quoted string (`like this`). This form isn't so much a literal string as a way to run external commands and get back their output. This form is covered in Chapter 14, Process Management. [5] Perl also has here strings, which we'll touch on in Chapter 18, CGI Programming.
Note that the \n within a single-quoted string is not interpreted as a newline, but as the two characters backslash and n. (Only when the backslash is followed by another backslash or a single quote does it have special meaning.)
Table 2.1: Double-Quoted String Representations Construct Meaning \n \r \t \f \b \v \a \e \007 \x7f \cC \\ \" \l \L Newline Return Tab Formfeed Backspace Vertical tab Bell Escape Any octal ASCII value (here, 007 = bell) Any hex ASCII value (here, 7f = delete) Any "control" character (here, control C) Backslash Doublequote Lowercase next letter Lowercase all following letters until \E
\u \U \Q \E
Uppercase next letter Uppercase all following letters until \E Backslash quote all nonalphanumerics Terminate \L , \U or \Q
Another feature of double-quoted strings is that they are variable interpolated, meaning that scalar and array variables within the strings are replaced with their current values when the strings are used. We haven't formally been introduced to what a variable looks like yet (except in the stroll), so I'll get back to this later. A quick note here about using DOS/Win32 pathnames in double-quoted strings: while Perl accepts either backslashes or forward slashes in path names, backslashes need to be escaped. So, you need to write one of the following: "c:\\temp" # use an escaped backslash "c:/temp" # use a Unix-style forward slash If you forget to escape the backslash, you'll end up with strange results: "c:\temp" # WRONG - this string contains a c:, a TAB, and emp If you're already used to using pathnames in C/C++, this notation will be second nature to you. Otherwise, beware: pathnames seem to bite each and every Perl-for-Win32 programmer from time to time.
Previous: 2.2 Numbers Learning Perl on Win32 Systems Book Index Next: 2.4 Scalar Operators
2.2 Numbers
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
You may be wondering about the word "approximately" in the code comments at the start of this section. Don't you get exactly 2.7 when subtracting 2.4 from 5.1? In math class you do, but on computers you usually don't. Instead, you get an approximation that's only accurate to a certain number of decimal places. Computers don't store numbers in the same way a mathematician does. Although there are infinitely many decimal points in them, the computer only has a limited space to store them (usually 64 bits per number). So, just a few of these infinite real numbers can be exactly represented on the computer - the rest are just close. Comparing the following statements, you'll see what the computer really got as the result of the subtraction (the printf function is described in Chapter 6, Basic I/O): printf("%.51f\n", 5.1 - 2.4) # 2.699999999999999733546474089962430298328399658203125 print(5.1 - 2.4, "\n"); # 2.7 Don't worry too much about this: the print() function's default format for printing floating-point numbers usually hides such minor representational inaccuracies. If this ends up being a problem, the Math::BigInt and Math::BigFloat object modules provide infinite-precision arithmetic for integers and floating-point numbers at the cost of somewhat slower execution. For details, see Chapter 7 of Programming Perl or the online documentation on these modules.
Table 2.2: Numeric and String Comparison Operators Comparison Equal Not equal Numeric String == != eq ne
lt gt le ge
You may wonder why there are separate operators for numbers and strings, if numbers and strings are automatically converted back and forth. Consider the two values 7 and 30. If compared as numbers, 7 is obviously less than 30, but if compared as strings, the string "30" comes before the string "7" (because the ASCII value for 3 is less than the value for 7), and hence is less. Perl always requires you to specify the proper type of comparison, whether it be numeric or string. Still another string operator is the string repetition operator, consisting of the single lowercase letter x. This operator takes its left operand (a string), and makes as many concatenated copies of that string as indicated by its right operand (a number). For example: "fred" x 3 # is "fredfredfred" "barney" x (4+1) # is "barney" x 5, or # "barneybarneybarneybarneybarney" (3+2) x 4 # is 5 x 4, or really "5" x 4, which is "5555" That last example is worth spelling out slowly. The parentheses on (3+2) force this part of the expression to be evaluated first, yielding five. (The parentheses here are working as in standard math.) But the string repetition operator wants a string for a left operand, so the number 5 is converted to the string "5" (using rules described in detail later), a one-character string. This new string is then copied four times, yielding the four-character string 5555. If we had reversed the order of the operands, we would have made five copies of the string 4, yielding 44444. This shows that string repetition is not commutative. If necessary, the copy count (the right operand) is first truncated to an integer value (4.8 becomes 4) before being used. A copy count of less than 1 results in an empty (zero-length) string.
While precedence is intuitive for addition and multiplication,[6] we start running into problems when faced with, say, string concatenation compared with exponentiation. You can resolve this by consulting the official, accept-no-substitutes Perl operator precedence chart, shown in Table 2.3. (Note that some of the operators have not yet been described, and in fact, may not even appear anywhere in this book, but don't let that fact scare you away from reading about them.) Operators also found in C have the same precedence as in C). [6] Asssuming you recall your high school algebra class. If not, simply use parentheses to improve clarity. Table 2.3: Associativity and Precedence of Operators Associativity Left Left Operator The "list" operators (leftward) -> (method call, dereference)
Nonassociative ++ -- (autoincrement, autodecrement) Right Right Left Left Left Left ** (exponentiation) ! ~ \ + - (logical not, bit not, reference operator, unary plus, unary minus) =~ !~ (matches, doesn't match) * / % x (multiply, divide, modulus, string replicate) + - . (add, subtract, string concatenate) << >> (shift operators)
Nonassociative Named unary operators (like chomp) Nonassociative < > <= >= lt gt le ge (relational operators) Nonassociative == != <=> eq ne cmp (equality operators) Left Left Left Left & (bit and) | ^ (bit or, bit xor) && (logical and) || (logical or)
Nonassociative .. ... (noninclusive and inclusive range) Right Right Left ?: (if then else) = += -= *=, etc. (assignment and binary assignment) , => (comma and comma arrow)
not (logical not) and (logical and) or xor (logical or, logical xor)
In Table 2.3, any given operator has higher precedence than those listed below it, and lower precedence than all of the operators listed above it. Operators at the same precedence level resolve according to rules of associativity. Just like precedence, associativity resolves the order of operations when two operators of the same precedence compete for three operands: 2 ** 3 ** 4 # 2 ** (3 ** 4), or 2 ** 81, or approx 2.41e24 72 / 12 / 3 # (72 / 12) / 3, or 6/3, or 2 30 / 6 * 3 # (30/6)*3, or 15 In the first case, the ** operator has right associativity, so the parentheses are implied on the right. Comparatively, the * and / operators have left associativity, yielding a set of implied parentheses on the left.
2.3 Strings
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
assignment form with an appended equal sign. For example, the following two lines are equivalent: $a = $a + 5; # without the binary assignment operator $a += 5; # with the binary assignment operator And so are these: $b = $b * 3; $b *= 3; In each case, the operator causes the existing value of the variable to be altered in some way, not simply overwriting the value with the result of some new expression. Another common assignment operator is the string concatenate operator: $str = $str . " "; # append a space to $str $str .= " "; # same thing with assignment operator Nearly all binary operators are valid in this way. For example, a raise to the power of operator is written as **=. So, $a **= 3 means "raise the number in $a to the third power, placing the result back in $a." Like the simple assignment operator, each of these operators has a value as well: the new value of the variable. For example: $a = 3; $b = ($a += 4); # $a and $b are both now 7
For example: $x = 12; --$x; # $x is now 11 $y = $x--; # $y is 11, and $x is now 10 The autoincrement and autodecrement operators also work on floating-point values. So autoincrementing a variable with the value 4.2 yields 5.2 as expected.[10] [10] Autoincrement even works on strings. See Programming Perl or perlop for related information.
$a = "hello world\n"; chomp ($a); # $a is now "hello world" chomp ($a); # aha! no change in $a
The text that replaces the variable is not rescanned; even if there are dollar signs in the replaced value, no further replacement occurs: $x = '$fred'; # literally a dollar sign followed by "fred" $y = "hey $x"; # value is 'hey $fred': no double substitution To prevent the substitution of a variable with its value, you must either alter that part of the string so that it appears in single quotes, or precede the dollar sign with a backslash, which turns off the dollar sign's special significance: $fred = 'hi'; $barney = "a test of " . '$fred';# literally: 'a test of $fred' $barney2 = "a test of \$fred"; # same thing The variable name will be the longest possible variable name that makes sense at that part of the string. This can be a problem if you want to follow the replaced value immediately with some constant text that begins with a letter, digit, or underscore. As Perl scans for variable names, it would consider those characters to be additional name characters, and this result is not what you want. Perl provides a delimiter for the variable name. Simply enclose the name of the variable in a pair of curly braces. Or, you can end that part of the string and start another part of the string with a concatenation operator: $fred = "pay"; $fredday = "wrong!"; $barney = "It's $fredday"; # not payday, but "It's wrong!" $barney = "It's ${fred}day"; # now, $barney gets "It's payday" $barney2 = "It's $fred"."day"; # another way to do it $barney3 = "It's " . $fred . "day"; # and another way You can use the case-shifting string escapes to alter the case of letters that are brought in with variable interpolation.[14] For example: [14] You may find the uc, ucfirst, lc, and lcfirst operators easier to use.
$bigfred = "\Ufred"; # $bigfred is "FRED" $fred = "fred"; $bigfred = "\U$fred"; # same thing $capfred = "\u$fred"; # $capfred is "Fred" $barney = "\LBARNEY"; # $barney is now "barney" $capbarney = "\u\LBARNEY"; # $capbarney is now "Barney" $bigbarney = "BARNEY"; $capbarney = "\u\L$bigbarney"; # same As you can see, the case-shifting string escapes are remembered within a string until they are used, so even though the first letter of BARNEY doesn't follow the \u, it remains uppercase because of the \u. The term variable interpolation is often used interchangeably with double-quote interpolation, because strings that are double quoted are subject to variable interpolation. So too, are backquoted strings, as described in Chapter 14.
Previous: 2.5 Scalar Variables Learning Perl on Win32 Systems Book Index Next: 2.7 <STDIN> as a Scalar Value
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
2.10 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
2.10 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that computes the circumference of a circle with a radius of 12.5. The circumference is 2 [pi] times the radius, or about 2 times 3.141592654. 2. Modify the program from the previous exercise to prompt for and accept a radius from the person running the program. 3. Write a program that prompts for and reads two numbers, and then prints out the result of the two numbers multiplied together. 4. Write a program that reads a string and a number, and then prints the string the number of times indicated by the number on separate lines. (Hint: use the x operator.)
Previous: 2.9 The Undefined Value Learning Perl on Win32 Systems Book Index Next: 3. Arrays and List Data
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 3
2.10 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
barney betty wilma ); # same thing One use of a list literal is as arguments to the print() function introduced earlier. Elements of the list are printed out without any intervening whitespace: print("The answer is ",$a,"\n"); # three element literal array This statement prints "The answer is" followed by a space, the value of $a, and a newline. Stay tuned for other uses for list literals.
Previous: 3.1 What Is a List or Array? Learning Perl on Win32 Systems Book Index Next: 3.3 Variables
3.3 Variables
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
3.3 Variables
An array variable holds a single list value (zero or more scalar values). Array variable names are similar to scalar variable names, differing only in the initial character, which is an at sign (@) rather than a dollar sign ($). For example: @fred # the array variable @fred @A_Very_Long_Array_Variable_Name @A_Very_Long_Array_Variable_Name_that_is_different Note that the array variable @fred is unrelated to the scalar variable $fred. Perl maintains separate namespaces for different types of things. The value of an array variable that has not yet been assigned is (), the empty list. An expression can refer to array variables as a whole, or it can examine and modify individual elements of the array.
Previous: 3.2 Literal Representation Learning Perl on Win32 Systems Book Index Next: 3.4 Array Operators and Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
3.4.1 Assignment
Probably the most important array operator is the array assignment operator, which gives an array variable a value. It is an equal sign, just like the scalar assignment operator. Perl determines whether the assignment is a scalar assignment or an array assignment by noticing whether the assignment is to a scalar or an array variable.[1] For example: [1] This applies to scalar or array "lvalues" as well as to simple variables. @fred = (1,2,3); # The fred array gets a three-element literal @barney = @fred; # now that is copied to @barney If you assign a scalar value to an array variable, the scalar value becomes the single element of an array: @huh = 1; # 1 is promoted to the list (1) automatically # that is, @huh now is (1) An array variable name may appear in a list-literal list. When the value of the list is computed, Perl replaces the array variable name with the current values of the array, like so: @fred = qw(one two); @barney = (4,5,@fred,6,7); # @barney becomes # (4,5,"one","two",6,7) @barney = (8,@barney); # puts 8 in front of @barney @barney = (@barney,"last"); # and a "last" at the end # @barney is now (8,4,5,"one","two",6,7,"last") Note that the inserted array elements are at the same level as the rest of the literals: a list cannot contain another list as an element.[2] [2] Although a list reference is permitted as a list element, it's not really a list as a list element. Still, it works out to nearly the same thing, allowing for multidimensional arrays. See Chapter 4 of Programming Perl or perllol for more details. If a list literal contains only variable references (not expressions), you can treat the list literal as a
variable. In other words, you can use it on the left side of an assignment. Each scalar variable in the list literal takes on the corresponding value from the list on the right side of the assignment. For example: ($a,$b,$c) = (1,2,3); # give 1 to $a, 2 to $b, 3 to $c ($a,$b) = ($b,$a); # swap $a and $b ($d,@fred) = ($a,$b,$c); # give $a to $d, and ($b,$c) to @fred ($e,@fred) = @fred; # remove the first element of @fred to $e # this makes @fred = ($c) and $e = $b If the number of elements you assign does not match the number of variables to hold the values, any excess values (on the right side of the equal sign) are silently discarded, and any excess variables (on the left side of the equal sign) are given the value of undef. An array variable appearing in the array literal list must be last, because the array variable is "greedy" and consumes all remaining values. (Well, you could put other variables after it, but they would just get undef values.) If you assign an array variable to a scalar variable, the number assigned is the length of the array, as in: @fred = (4,5,6); # initialize @fred $a = @fred; # $a gets 3, the current length of @fred The length is also returned whenever you use an array variable name where a scalar value is needed. (In the section "Scalar and List Context" later in this chapter, we'll see that this method is called using the array name in a scalar context.) For example, to get one less than the length of the array, you can use @fred-1, because the scalar subtraction operator wants scalars for both of its operands. Notice the following: $a = @fred; # $a gets the length of @fred ($a) = @fred; # $a gets the first element of @fred The first assignment is a scalar assignment, and so @fred is treated as a scalar, yielding its length. The second assignment is an array assignment (even if only one value is wanted), and thus yields the first element of @fred, silently discarding all the rest. The value of an array assignment is itself a list value, and can be cascaded as with scalar assignments. For example: @fred = (@barney = (2,3,4)); # @fred and @barney get (2,3,4) @fred = @barney = (2,3,4); # same thing
assigned to or have its current value used in an expression, like so: [3] You can change the index value of the first element to something else (like 1). However, doing so has drastic effects, will probably confuse people maintaining your code, and might break the routines you take from other people. Thus, we highly recommend that you consider this feature unusable. @fred = (7,8,9); $b = $fred[0]; # give 7 to $b (first element of @fred) $fred[0] = 5; # now @fred = (5,8,9) Other elements can be accessed with equal ease, as in: $c = $fred[1]; # give 8 to $c $fred[2]++; # increment the third element of @fred $fred[1] += 4; # add 4 to the second element ($fred[0],$fred[1]) = ($fred[1],$fred[0]); # swap the first two Accessing a list of elements from the same array (as in the previous example) is called a slice, and occurs often enough so that a special representation exists for it: @fred[0,1] # same as ($fred[0],$fred[1]) @fred[0,1] = @fred[1,0] # swap the first two elements @fred[0,1,2] = @fred[1,1,1] # make all 3 elements like the 2nd @fred[1,2] = (9,10); # change the last two values to 9 and 10 Note that this slice uses an @ prefix rather than a $. This is because you are creating an array variable by selecting part of the array rather than a scalar variable accessing just one element. Slices also work on literal lists, or any function that returns a list value: @who = (qw(fred barney betty wilma))[2,3]; # like @x = qw(fred barney betty wilma); @who = @x[2,3]; The index values in these examples have been literal integers, but the index can also be any expression that returns a number, which is then used to select the appropriate element: @fred = (7,8,9); $a = 2; $b = $fred[$a]; # like $fred[2], or the value of 9 $c = $fred[$a-1]; # $c gets $fred[1], or 8 ($c) = (7,8,9)[$a-1]; # same thing using slice Perl programs can thus have array accesses similar to many traditional programming languages. This idea of using an expression for the subscript also works for slices. Remember, however, that the subscript for a slice is a list of values, so the expression is an array expression, rather than a scalar expression. For example: @fred = (7,8,9); # as in previous example @barney = (2,1,0); @backfred = @fred[@barney]; # same as @fred[2,1,0], or ($fred[2],$fred[1],$fred[0]), or
# (9,8,7) If you access an array element beyond the ends of the current array (that is, an index of less than 0 or greater than the last element's index), the undef value is returned without warning. For example: @fred = (1,2,3); $barney = $fred[7]; # $barney is now undef Assigning a value beyond the end of the current array automatically extends the array (giving a value of undef to all intermediate values, if any). For example: @fred = (1,2,3); $fred[3] = "hi"; # @fred is now (1,2,3,"hi") $fred[6] = "ho"; # @fred is now (1,2,3,"hi",undef,undef,"ho") Assignment to an array element with a subscript of less than 0 is a fatal error, because it is probably the result of Very Bad Programming Style. You can use $#fred to get the index value of the last element of @fred. You can even assign to this value to change the apparent length of @fred, making it grow or shrink, but such an assignment is generally unnecessary, because the array grows and shrinks automatically. A negative subscript on an array counts back from the end. So, another way to get at the last element is with the subscript -1. The second to the last element would be -2, and so on. For example: @fred = ("fred", "wilma", "pebbles", "dino"); print $fred[-1]; # prints "dino" print $#fred; # prints 3 print $fred[$#fred]; # prints "dino"
3.3 Variables
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
name reference with a literal left bracket rather than an indexing expression.
Previous: 3.6 <STDIN> as an Array Learning Perl on Win32 Systems Book Index Next: 3.8 Exercises
3.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
3.8 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that reads a list of strings on separate lines and prints out the list in reverse order. If you're reading the list from the console, you'll probably need to delimit the end of the list by pressing CTRL-Z. 2. Write a program that reads a number and then a list of strings (all on separate lines), and then prints one of the lines from the list as selected by the number. 3. Write a program that reads a list of strings and then selects and prints a random string from the list. To select a random element of @somearray, put srand; at the beginning of your program (this initializes the random number generator), and then use rand(@somearray) where you need a random value between 0 and 1 less than the length of @somearray.
Previous: 3.7 Variable Interpolation of Arrays Learning Perl on Win32 Systems Book Index Next: 4. Control Structures
4. Control Structures
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 4
4. Control Structures
Contents: Statement Blocks The if/unless Statement The while/until Statement The do {} while/until Statement The for Statement The foreach Statement Exercises
$sleepy = ($hungry + 1) * 2; }
Previous: 3.8 Exercises Learning Perl on Win32 Systems Book Index Next: 4.2 The if/unless Statement
3.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
# # # #
"0", so true "0", so true (this one is weird, watch out) for the same reason and warning to "", so false
Practically speaking, interpretation of values as true or false is fairly intuitive. Don't let us scare you. Here's an example of a complete if statement: print "how old are you? "; $a = <STDIN>; chomp($a); if ($a < 18) { print "So, you're not old enough to vote, eh?\n"; } else { print "Old enough! Cool! So go vote!\n"; $voter++; # count the voters for later } You can omit the else block, leaving just a then part, as in: print "how old are you? "; $a = <STDIN>; chomp($a); if ($a < 18) { print "So, you're not old enough to vote, eh?\n"; } Sometimes, you want to leave off the then part and have just an else part, because saying "do that if this is false," is more natural than saying "do that if not this is true." Perl handles this case with the unless variation: print "how old are you? "; $a = <STDIN>; chomp($a); unless ($a < 18) { print "Old enough! Cool! So go vote!\n"; $voter++; } Replacing if with unless is in effect saying, "If the control expression is false, do..." (An unless can also have an else, just like an if.) If you have more than two possible choices, add an elsif branch to the if statement, like so: if (some_expression_one) { one_true_statement_1; one_true_statement_2; one_true_statement_3; } elsif (some_expression_two) { two_true_statement_1;
two_true_statement_2; two_true_statement_3; } elsif (some_expression_three) { three_true_statement_1; three_true_statement_2; three_true_statement_3; } else { all_false_statement_1; all_false_statement_2; all_false_statement_3; } Each expression (here, some_expression_one, some_expression_two, and some_expression_three) is computed in turn. If an expression is true, the corresponding branch is executed, and all remaining control expressions and corresponding statement blocks are skipped. If all expressions are false, the else branch is executed (if there is one). You don't have to have an else block, but having one is always a good idea. You may have as many elsif branches as you wish.
Previous: 4.1 Statement Blocks Learning Perl on Win32 Systems Book Index Next: 4.3 The while/until Statement
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Sometimes the control expression never lets the loop exit. This case is perfectly legal, and sometimes desired, and is thus not considered an error. For example, you might want a loop to repeat as long as you have no error, and then have some error handling code following the loop. You might use this for a program that is meant to run until the system terminates.
Previous: 4.2 The if/unless Statement Learning Perl on Win32 Systems Book Index Next: 4.4 The do {} while/until Statement
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
shorter construct is more legible than the longer one. If the list you are iterating over is made of real variables rather than some function returning a list value, then the variable being used for iteration is in fact an alias for each variable in the list instead of being merely a copy of the values. Consequently, if you change the scalar variable, you are also changing that particular element in the list that the variable is standing in for. For example: @a = (3,5,7,9); foreach $one (@a) { $one *= 3; $x = 17; @a = (3,5,7,9); @b = (10,20,30); foreach $one (@a, @b, $x) { $one *= 3; } # $x is now 51 # @a is now (9,15,21,27) # @b is now (30,60,90); } # @a is now (9,15,21,27) Notice how altering $one in fact altered each element of @a.
Previous: 4.5 The for Statement Learning Perl on Win32 Systems Book Index Next: 4.7 Exercises
4.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Next: 5. Hashes
4.7 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that asks for the temperature outside, and prints "too hot" if the temperature is above 72, and "too cold" otherwise. 2. Modify the program from the previous exercise so that it prints "too hot" if the temperature is above 75, "too cold" if the temperature is below 68, and "just right!" if it is between 68 and 75. 3. Write a program that reads a list of numbers (on separate lines) until the number 999 is read, and then prints the total of all the numbers added together. (Be sure not to add in the 999!) For example, if you enter 1, 2, 3, and 999, the program should reply with the answer of 6 (1+2+3). 4. Write a program that reads in a list of strings on separate lines and then prints out the list of strings in reverse order - without using reverse on the list. (Recall that <STDIN> will read a list of strings on separate lines when used in an array context.) 5. Write a program that prints a table of numbers and their squares from 0 to 32. Try to come up with a way in which you don't need to have all the numbers from 0 to 32 in a list, and then try a way in which you do. (For nice looking output, printf "%5g %8g\n", $a, $b prints $a as a five-column number and $b as an eight-column number.)
Previous: 4.6 The foreach Statement Learning Perl on Win32 Systems Book Index Next: 5. Hashes
5. Hashes
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5
5. Hashes
Contents: What Is a Hash? Hash Variables Literal Representation of a Hash Hash Functions Hash Slices Exercises
4.7 Exercises
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5 Hashes
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5 Hashes
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5 Hashes
In fact, merely using %somehash in a scalar context will reveal whether the hash is empty or not: if (%somehash) { # if true, then something's in it # do something with it }
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5 Hashes
5.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 5 Hashes
5.6 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that reads in a string, then prints that string and its mapped value according to the mapping presented in Table 5.1.
2. Write a program that reads a series of words with one word per line until end-of-file, then prints a summary of how many times each word was seen. (For extra challenge, sort the words in ascending ASCII order in the output.)
Previous: 5.5 Hash Slices Learning Perl on Win32 Systems Book Index Next: 6. Basic I/O
6. Basic I/O
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 6
6. Basic I/O
Contents: Input from STDIN Input from the Diamond Operator Output to STDOUT Exercises
while (<STDIN>) { # like "while(defined($_ = <STDIN>_)" chomp; # like "chomp($_)" # other operations with $_ here } Because the $_ variable is the default for many operations, you can save a noticeable amount of typing this way.
Previous: 5.6 Exercises Learning Perl on Win32 Systems Book Index Next: 6.2 Input from the Diamond Operator
5.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
and finally a newline. Among the many formats supported by Perl's printf() and sprintf() functions are the following commonly used ones: %% Percent sign %c %s Character with the given number String
%d Signed integer, in decimal %u Unsigned integer, in decimal %o Unsigned integer, in octal %x Unsigned integer, in hexadecimal %e %f Floating-point number, in scientific notation Floating-point number, in fixed decimal notation
%g Floating-point number, in %e or %f notation Between the percent and the format character, you may place one or more of the following flags: space + 0 Prefix positive number with a space Prefix positive number with a plus sign Left justify within the field Use zeros, not spaces, to right justify
number Minimum field width .number Precision: digits after decimal point for floating-point number, maximum length for string, minimum length for integer
Previous: 6.2 Input from the Diamond Operator Learning Perl on Win32 Systems Book Index Next: 6.4 Exercises
6.4 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
6.4 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that acts like type, but reverses the order of the lines from the files specified on the command line, or all the lines from standard input if no files are specified. 2. Modify the program from the previous exercise so that each file specified on the command line has its lines individually reversed. (Yes, you can do this with only what's been shown to you so far, even excluding the stroll in Chapter 1, Introduction.) 3. Write a program that reads a list of strings on separate lines, and prints the strings in a right-justified 20-character column. For example, inputting hello, good-bye prints hello and good-bye, right-justified in a 20-character column. (Be sure your program is actually using a 20-character column, and not a 21-character column. That mistake is common.) 4. Modify the program from the previous exercise to allow the user to select the column width. For example, entering 20, hello, and good-bye should do the same thing as the previous program did; but, entering 30, hello, and good-bye should justify hello and good-bye in a 30-character column.
Previous: 6.3 Output to STDOUT Learning Perl on Win32 Systems Book Index Next: 7. Regular Expressions
7. Regular Expressions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 7
7. Regular Expressions
Contents: Concepts About Regular Expressions Simple Uses of Regular Expressions Patterns More on the Matching Operator Substitutions The split and join Functions Exercises
6.4 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
if (/ab*c/) { print $_; } } Just like findstr, this loop looks for an a followed by zero or more b's followed by a c. We'll visit more uses of pattern matching in the section "More on the Matching Operator," later in the chapter, after we talk about all kinds of regular expressions. Another simple regular expression operator is the substitute operator, which replaces the part of a string that matches the regular expression with another string. The substitute operator consists of the letter s, a slash, a regular expression, a slash, a replacement string, and a final slash, looking something like: s/ab*c/def/; The variable (in this case, $_) is matched against the regular expression (ab*c). If the match is successful, the part of the string that matched is discarded and replaced by the replacement string (def). If the match is unsuccessful, nothing happens. As with the match operator, we'll revisit the myriad options on the substitute operator later, in the section "Substitutions."
Previous: 7.1 Concepts About Regular Expressions Learning Perl on Win32 Systems Book Index Next: 7.3 Patterns
7.3 Patterns
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
7.3 Patterns
A regular expression is a pattern. Some parts of the pattern match single characters in the string of a particular type. Other parts of the pattern match multiple characters. First, we'll visit the single-character patterns, and then the multiple-character patterns.
(or caret: ^) immediately after the left bracket. This character class matches any single character that is not in the list. For example: [^0-9] # match any single non-digit [^aeiouAEIOU] # match any single non-vowel [^\^] # match single character except an up-arrow For your convenience, some common character classes are predefined, as described in Table 7.1.
Table 7.1: Predefined Character Class Abbreviations Construct \d (a digit) Equivalent Class Negated Construct Equivalent Negated Class [0-9] \D (digits, not!) \W (words, not!) \S (space, not!) [^0-9] [^a-zA-Z0-9_] [^ \r\t\n\f]
The \d pattern matches one digit. The \w pattern matches one word character, although the pattern is really matching any character that is legal in a Perl variable name. The \s pattern matches one space (whitespace), defined here as spaces, carriage returns, tabs, line feeds, and form feeds. The uppercase versions match the complements of these classes. Thus, \W matches one character that can't be in an identifier, \S matches one character that is not a whitespace (including letters, punctuation marks, control characters, etc.), and \D matches any single non-digit character. These abbreviated classes can be used as part of other character classes as well: [\da-fA-F] # match one hex digit
more o's, followed by a b, followed by an optional a, followed by an r. In all three of these grouping patterns, the patterns are greedy. If such a multiplier has a chance to match between five and ten characters, it'll pick the ten-character string every time. For example, $_ = "fred xxxxxxxxxx barney"; s/x+/boom/; always replaces all consecutive x's with boom (resulting in fred boom barney), rather than just one or two x's, even though a shorter set of x's would also match the same regular expression. If you need to say "five to ten" x's, you could get away with putting five x's followed by five x's each immediately followed by a question mark. But this looks ugly. Instead, an easier way exists: the general multiplier. The general multiplier consists of a pair of matching curly braces with one or two numbers inside, as in /x{5,10}/. The immediately preceding character (in this case, the letter x) must be found within the indicated number of repetitions (five through ten here).[1] [1] Of course, /\d{3}/ doesn't only match three-digit numbers. It would also match any number containing more than three digits. To match exactly three, you need to use anchors, described in the next section, titled "Anchoring Patterns." If you leave off the second number, as in /x{5,}/, you indicate "that many or more" (five or more in this case), and if you leave off the comma, as in /x{5}/, you indicate "exactly this many" (five x's). To get five or fewer x's, you must put the zero in, as in /x{0,5}/. So, the regular expression /a.{5}b/ matches the letter a separated from the letter b by any five non-newline characters at any point in the string. (Recall that a period matches any single non-newline character, and we're matching five here.) The five characters do not need to be the same. (We'll learn how to force them to be the same in the next section.) We could dispense with *, +, and ? entirely, because they are completely equivalent to {0,}, {1,}, and {0,1}. But it's easier to type the equivalent single punctuation character, and more familiar as well. If two multipliers occur in a single expression, the greedy rule is augmented with leftmost is greediest. For example: $_ = "a xxx c xxxxxxxx c xxx d"; /a.*c.*d/; In this case, the first .* in the regular expression matches all characters up to the second c, even though matching only the characters up to the first c would still allow the entire regular expression to match. Right now, this distinction is not important (the pattern would match either way), but later when we can look at parts of the regular expression that matched, the distinction will matter quite a bit. We can force any multiplier to be nongreedy (or lazy) by following it with a question mark: $_ = "a xxx c xxxxxxxx c xxx d"; /a.*?c.*d/; Here, the a.*?c matches the fewest characters between the a and c, not the most characters. This means the leftmost c is matched, not the rightmost. You can put such a question-mark modifier after any of the multiplers (?,+,* and {m,n}).
What if the string and regular expression were slightly altered, say, to: $_ = "a xxx ce xxxxxxxx ci xxx d"; /a.*ce.*d/; In this case, if the .* matches the most characters possible before the next c, the next regular expression character (e) doesn't match the next character of the string (i). In this case, we get automatic backtracking. The multiplier is unwound and retried, stopping at someplace earlier (in this case, at the earlier c, next to the e).[2] A complex regular expression may involve many such levels of backtracking, leading to long execution times. In this case, consider that making that match lazy (with a trailing ?) will actually simplify the work that Perl has to perform. [2] Well, technically, there was a lot of backtracking of the * operator to find the c's in the first place. But that's a little trickier to describe, and it works on the same principle. 7.3.2.3 Parentheses as memory Another grouping operator is a pair of open and close parentheses around any part pattern. This operator doesn't change whether the pattern matches, but instead causes the part of the string matched by the pattern to be remembered, so that it may be referenced later. So, for example, (a) still matches an a, and ([a-z]) still matches any single lowercase letter. To recall a memorized part of a string, you must include a backslash followed by an integer. This pattern construct represents the same sequence of characters matched earlier in the same-numbered pair of parentheses (counting from one). For example: /fred(.)barney\1/; matches a string consisting of fred, followed by any single non-newline character, followed by barney, followed by that same single character. So, the string matches fredxbarneyx, but not fredxbarneyy. Compare that string with: /fred.barney./; in which the two unspecified characters can be the same, or different. Where did the 1 come from? The 1 indicates the first parenthesized part of the regular expression. If there's more than one, the second part (counting the left parentheses from left to right) is referenced as \2, the third as \3, and so on. For example: /a(.)b(.)c\2d\1/; matches an a, a character (call it #1), a b, another character (call it #2), a c, the character #2, a d, and the character #1. So, the string matches axbycydx, for example. The referenced part can be more than a single character. For example, /a(.*)b\1c/; matches an a, followed by any number of characters (even zero), followed by b, followed by that same sequence of characters, followed by c. So, the string would match aFREDbFREDc, or even abc, but not aXXbXXXc.
7.3.2.4 Alternation Another grouping construct is alternation, as in a|b|c. This construct matches exactly one of the alternatives (a or b or c, in this case). This construct works even if the alternatives have multiple characters, as in /song|blue/, which matches either song or blue. (For single-character alternatives, you're definitely better off with a character class like /[abc]/.) What if we wanted to match songbird or bluebird? We could write /songbird|bluebird/, but that bird part shouldn't have to be in there twice. In fact, there's a way out, but we have to talk about the precedence of grouping patterns, which is covered later in the section "Precedence."
anchors are described fully in Chapter 2 of Programming Perl and the perlre documentation.
7.3.4 Precedence
So what happens when we get a|b* together? Is this a or b any number of times, or is it either a single a or any number of b's? Well, just as operators have precedence, the grouping and anchoring patterns also have precedence. The precedence of patterns from highest to lowest is given in Table 7.2.
Table 7.2: regex Grouping Precedence [4] Name Parentheses Multipliers Representation ( ) (?: ) ? + * {m,n} ?? +? *? {m,n}
[4] Some of these symbols are not described in this book. See Programming Perl or perlre for details. According to the table, * has a higher precedence than |. So /a|b*/ is interpreted as a single a, or any number of b's. What if we want the other meaning, as in "any number of a's or b's"? We simply throw in a pair of parentheses. In this case, we enclose the part of the expression that the * operator should apply to inside parentheses, and we are done, as (a|b)*. If you want to clarify the first expression, you can redundantly parenthesize it with a|(b*). When you use parentheses to affect precedence they also trigger the memory, as shown earlier in this chapter. That is, this set of parentheses counts when you are figuring out whether something is \2, \3, or whatever. If you want to use parentheses without triggering memory, use the form (?:...) instead of (...). This form still allows for multipliers, but doesn't cause you to throw off your counting by using up another $4 or whatever. For example, /(?:Fred|Wilma) Flintstone/ does not store anything into $1; it's just there for grouping. Here are some other examples of regular expressions, and the effect of parentheses: abc* # matches ab, abc, abcc, abccc, abcccc, and so on (abc)* # matches "", abc, abcabc, abcabcabc, and so on ^x|y # matches x at the beginning of line, or y anywhere ^(x|y) # matches either x or y at the beginning of a line a|bc|d # a, or bc, or d (a|b)(c|d) # ac, ad, bc, or bd (song|blue)bird # songbird or bluebird
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
$_ = "this is a test"; /(\w+)\W+(\w+)/; # match first two words # $1 is now "this" and $2 is now "is" You can also gain access to the same values ($1, $2, $3, and so on) by placing a match in a list context. The result is a list of values from $1 up to the number of memorized things, but only if the regular expression matches. (Otherwise, the variables are undefined.) Taking that last example in another way: $_ = "this is a test"; ($first, $second) = /(\w+)\W+(\w+)/; # match first two words # $first is now "this" and $second is now "is" Other predefined read-only variables include $&, which is the part of the string that matched the regular expression; $`, which is the part of the string before the part that matched; and $', which is the part of the string after the part that matched. For example: $_ = "this is a sample string"; /sa.*le/; # matches "sample" within the string # $` is now "this is a " # $& is now "sample" # $' is now " string" Because these variables are set on each successful match, you should save the values elsewhere if you need them later in the program.[6] [6] See O'Reilly's Mastering Regular Expressions for the performance ramifications of using these variables.
Previous: 7.3 Patterns Learning Perl on Win32 Systems Book Index Next: 7.5 Substitutions
7.3 Patterns
7.5 Substitutions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
7.5 Substitutions
We've already talked about the simplest form of the substitution operator: s/old-regex/new-string/. We can now discuss a few variations of this operator. If you want the replacement to operate on all possible matches instead of just the first match, append a g to the substitution, as in: $_ = "foot fool buffoon"; s/foo/bar/g; # $_ is now "bart barl bufbarn" The replacement string is variable interpolated, allowing you to specify the replacement string at runtime: $_ = "hello, world" $new = "goodbye"; s/hello/$new/; # replaces hello with goodbye Pattern characters in the regular expression allow patterns to be matched, rather than just fixed characters: $_ = "this is a test"; s/(\w+)/<$1>/g; # $_ is now "<this> <is> <a> <test>" Recall that $1 is set to the data within the first parenthesized pattern match. An i suffix (either before or after the g, if present) causes the regular expression in the substitute operator to ignore case, just like the same option on the match operator described earlier. As with the match operator, an alternate delimiter can be selected if the slash is inconvenient. Just use the same character three times:[7] [7] Or, use two matching pairs if a left-right pair character is used. s#fred#barney#; # replace fred with barney, like s/fred/barney/ Also as with the match operator, you can specify an alternate target with the =~ operator. In this case, the selected target must be something you can assign a scalar value to, such as a scalar variable or an element of an array. Here's an example: $which = "this is a test"; $which =~ s/test/quiz/; # $which is now "this is a quiz"
$someplace[$here] =~ s/left/right/; # change an array element $d{"t"} =~ s/^/x /; # prepend "x " to hash element
Previous: 7.4 More on the Matching Operator Learning Perl on Win32 Systems Book Index Next: 7.6 The split and join Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
$line = "c:/;c:/windows;c:/windows/system;"; ($first, $second, $third, $fourth) = split(/;/,$line); # split $line, using ; as delimiter would simply give $fourth a null (undef) value if the line isn't long enough, or if it contained empty values in the last field. (Extra fields are silently ignored, because list assignment works that way.)
7.5 Substitutions
7.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Next: 8. Functions
7.7 Exercises
See Appendix A, Exercise Answers for answers. 1. Construct a regular expression that matches: (a) At least one a followed by any number of b's (b) Any number of backslashes followed by any number of asterisks (any number might be zero) (c) Three consecutive copies of whatever is contained in $whatever (d) Any five characters, including newline (e) The same word written two or more times in a row (with possibly varying intervening whitespace), where "word" is defined as a nonempty sequence of nonwhitespace characters 2. (a) Write a program that accepts a list of words on STDIN and looks for a line containing all five vowels (a, e, i, o, and u). Run this program on some large text file and see what shows up. In other words, enter: > perl myprogram.plx < mytextfile (This presumes you name your program myprogram.plx.) (b) Modify the program so that the five vowels have to be in order, and intervening letters don't matter. (c) Modify the program so that all vowels must be in an increasing order; all five vowels have to be present; and no "e" can occur before an "a", no "i" can occur befor an "e", and so on.
Previous: 7.6 The split and join Functions Learning Perl on Win32 Systems Book Index Next: 8. Functions
8. Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8
8. Functions
Contents: Defining a User Function Invoking a User Function Return Values Arguments Private Variables in Functions Semiprivate Variables Using local File-Level my( ) Variables Exercises We've already seen and used predetermined, built-in functions, such as chomp, print, and so on. Now, let's take a look at functions that you define yourself.
executed, and any return value (described later) is returned to the caller. Here, for example, is a subroutine that displays that famous phrase: sub say_hello { print "hello, world!\n"; } Subroutine definitions can be anywhere in your program text (they are skipped on execution), but we like to put them at the end of the file, so that the main part of the program appears at the beginning of the file. (If you like to think in Pascal terms, you can put your subroutines at the beginning and your executable statements at the end, instead. It's up to you.) Subroutine definitions are global;[2] there are no local subroutines. If you have two subroutine definitions with the same name, the later one overwrites the earlier one without warning.[3] [2] They are global to the current package, actually, but since this book doesn't really deal with separate packages, you may think of subroutine definitions as global to the whole program. [3] This statement is true, unless you are running with the -w switch. Within the subroutine body, you may access or give values to variables that are shared with the rest of the program (a global variable). In fact, by default, any variable reference within a subroutine body refers to a global variable. We'll tell you about the exceptions in the later section entitled "Private Variables in Functions." In the following example: sub say_what { print "hello, $what\n"; } $what refers to the the global $what, which is shared with the rest of the program.
Previous: 7.7 Exercises Learning Perl on Win32 Systems Book Index Next: 8.2 Invoking a User Function
7.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
} These examples are all rather trivial. It gets better when we can pass values that are different for each invocation into a subroutine, instead of having to rely on global variables. In fact, this discussion is coming right up.
Previous: 8.2 Invoking a User Function Learning Perl on Win32 Systems Book Index Next: 8.4 Arguments
8.4 Arguments
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
8.4 Arguments
Although subroutines that have one specific action are useful, a whole new level of usefulness becomes available when you can pass arguments to a subroutine. In Perl, the subroutine invocation (with the ampersand and the subroutine name) is followed by a list within parentheses, causing the list to be automatically assigned to a special variable named @_ for the duration of the subroutine. The subroutine can access this variable to determine the number of arguments and the value of those arguments. For example: sub say_hello_to { print "hello, $_[0]!\n"; # first parameter is target } Here, we see a reference to $_[0], which is the first element of the @_ array. Special note: although similar in appearance, the $_[0] value (the first element of the @_ array) has nothing whatsoever to do with the $_ variable (a scalar variable of its own). Don't confuse them! The code seems to say hello to whomever we pass as the first parameter. As a result, we can invoke it like this: say_hello_to("world"); # gives hello, world! $x = "somebody"; say_hello_to($x); # gives hello, somebody! say_hello_to("me") + say_hello_to("you"); # and me and you Note that in the last line, the return values weren't really used. But in evaluating the sum, Perl has to evaluate all of its parts, so the subroutine was invoked twice. Here's an example using more than one parameter: sub say { print "$_[0], $_[1]!\n"; } say("hello","world"); # hello world, once again say("goodbye","cruel world"); # silent movie lament Excess parameters are ignored: if you never look at $_[3], Perl doesn't care. And insufficient parameters are also ignored; you simply get undef if you look beyond the end of the @_ array, as with any other array.
The @_ variable is private to the subroutine; if there's a global value for @_, it is saved away before the subroutine is invoked and restored to its previous value upon return from the subroutine. This also means that a subroutine can pass arguments to another subroutine without fear of losing its own @_ variable; the nested subroutine invocation gets its own @_ in the same way. Let's revisit that "add a and b" routine from the previous section. Here's a subroutine that adds any two values (specifically, the two values passed to the subroutine as parameters): sub add_two { $_[0] + $_[1]; } print add_two(3,4); # prints 7 $c = add_two(5,6); # $c gets 11 Now let's generalize this subroutine. What if we had 3, 4, or 100 values to add together? We could do it with a loop, as shown: sub add { $sum = 0; # initialize the sum foreach $_ (@_) { $sum += $_; # add each element } return $sum; # the sum of all elements } $a = add(4,5,6); # adds 4+5+6 = 15, and assigns to $a print add(1,2,3,4,5); # prints 15 print add(1..5); # also prints 15, because 1..5 is expanded What if we had a variable named $sum when we called add? We just clobbered it. In the next section, we see how to avoid this situation.
Previous: 8.3 Return Values Learning Perl on Win32 Systems Book Index Next: 8.5 Private Variables in Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
with a variable reference instead. This change makes the program look like: sub bigger_than { my($n,@values); # create some local variables ($n,@values) = @_; # split args into limit and values my(@result); # temporary for holding the return value foreach $_ (@values) { # step through the arg list if ($_ > $n) { # is it eligible? push(@result,$_); # add it } } @result; # return the final list } # some invocations: @new = bigger_than(100,@list); # @new gets all @list > 100 @this = bigger_than(5,1,5,15,30); # @this gets (15,30) Notice that this time, we used two additional local variables to give names to arguments. This method is fairly common in practice - you can more easily talk about $n and @values than talk about $_[0] and @_[1..$#_], and $n and @values are safer as well. The result of my is an assignable list, meaning that it can be used on the left side of an array assignment operator. You can give this list initial values for each of the newly created variables. (If you don't give values to the list, the new variables start with a value of undef, just like any other new variable.) As a result, we can combine the first two statements of this subroutine, replacing: my($n,@values); ($n,@values) = @_; # split args into limit and values with: my($n,@values)= @_; This is, in fact, a very common Perl-ish thing to do. Local nonargument variables can be given literal values in the same way, such as: my($sum) = 0; # initialize local variable Be warned that despite its appearance as a declaration, my is really an executable operator. Good Perl hacking strategy suggests that you bunch all of your my operators at the beginning of the subroutine definition, before you get into the meat of the routine.
Previous: 8.4 Arguments Learning Perl on Win32 Systems Book Index Next: 8.6 Semiprivate Variables Using local
8.4 Arguments
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
preserved and automatically restored when the function exits. In your more advanced programming efforts, you may eventually need to know that local variables are really global variables in disguise. That is, the value of the global variable is saved and temporarily replaced with the locally declared value. By and large, you should prefer to use my over local because my is faster and safer.
Previous: 8.5 Private Variables in Functions Learning Perl on Win32 Systems Book Index Next: 8.7 File-Level my( ) Variables
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
Your programs will run slightly faster (variables created with my are accessed slightly faster than ordinary variables[5]). [5] In this case, ordinary variable is really a package variable (so $x is really $main::x). Variables created with my are not found in any package.
You'll catch mistakes in typing much faster, because you'll no longer be able to accidentally reference a nonexisting variable named $freed when you wanted $fred.
Because of these advantages, many Perl programmers automatically begin every new Perl program with use strict.
8.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 8 Functions
8.8 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a subroutine that takes a numeric value from 1 to 9 as an argument and then returns the English name (such as, one, two, or nine). If the value is out of range, return the original number as the name instead. Test it with some input data; you'll probably have to write some sort of code to call the subroutine. (Hint: the subroutine should not perform any I/O.) 2. Taking the subroutine from the previous exercise, write a program that takes two numbers and then adds them together, displaying the result as Two plus two equals four. (Don't forget to capitalize the initial word!) 3. Extend the subroutine to return negative nine through negative one and zero. Try it in a program.
Previous: 8.7 File-Level my( ) Variables Learning Perl on Win32 Systems Book Index Next: 9. Miscellaneous Control Structures
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 9
If somecondition is true, the somethingorothers are executed, and then the last forces the while loop to terminate. The last statement counts only looping blocks, not other blocks that are needed to make up some syntactic construct. As a result, the blocks for the if and else statement, as well as the one for a do {} while/until, do not count; only the blocks that make up the for, foreach, while, until, and "naked" blocks count. (A naked block is a block that is not otherwise part of a larger construct, such as a loop, subroutine, or if/then/else statement.) Suppose we wanted to see whether a mail message that had been saved in a file was from Erik. Such a message might look like: From: [email protected] (Erik Olson) To: [email protected] Date: 01-MAY-97 08:16:24 PM MDT -0700 Subject: A sample mail message Here's the body of the mail message. And here is some more. We'd have to look through the message for a line that begins with From:, and then notice whether the line also contains the login name, eriko. We could do it this way: while (<STDIN>) { # if (/^From: /) { # if (/eriko/) { # print "Email } last; # } # if (/^$/) { # last; # } } # read does it's from the input lines it begin with From:? If yes... from Erik! Erik! It's about time!\n";
no need to keep looking for From:, so exit end "if from:" blank line? if so, don't check any more lines end while
After the line starting with From: is found, we exit the main loop because we want to see only the first From: line. Also, because a mail message header ends at the first blank line, we can exit the main loop there as well.
Previous: 8.8 Exercises Learning Perl on Win32 Systems Book Index Next: 9.2 The next Statement
8.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
This logic would be appropriate for a while-like loop that needed to have some part of the loop executed as initialization before the first test. (In a later section entitled "Expression Modifiers," we'll show you how to write that if statement with fewer punctuation characters.)
Previous: 9.2 The next Statement Learning Perl on Win32 Systems Book Index Next: 9.4 Labeled Blocks
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
if ($j >= $i) { next OUTER; } } } This set of statements tries all successive values of two small numbers multiplied together until it finds a pair whose product is 63 (7 and 9). After the pair is found, there's no point in testing other numbers, so the first if statement exits both for loops using last with a label. The second if ensures that the bigger of the two numbers will always be the first number by skipping to the next iteration of the outer loop as soon as the condition would no longer hold. This means that the numbers will be tested with ($i, $j) being (1,1), (2,1), (2,2), (3,1), (3,2), (3,3), (4,1), and so on. Even if the innermost block is labeled, the last, next, and redo statements without the optional parameter (the label) still operate with respect to that innermost block. Also, you can't use labels to jump into a block - just out of a block. The last, next, or redo has to be within the block.
Previous: 9.3 The redo Statement Learning Perl on Win32 Systems Book Index Next: 9.5 Expression Modifiers
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Once again, we gain some clarity and reduce the clutter. These forms don't nest: you can't say exp3 while exp2 if exp1. This restriction is because the form exp2 if exp1 is no longer an expression, but a full-blown statement, and you can't tack one of these modifiers on after a statement.
Previous: 9.4 Labeled Blocks Learning Perl on Win32 Systems Book Index Next: 9.6 &&, ||, and ?: as Control Structures
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
If this is true, then the value of the entire expression is still not known, because it depends on the value of that. So that has to be evaluated. If this is false, there's no point in looking at that, because the value of the whole expression has to be false. Because you don't have to evaluate that, we might as well skip it.
And in fact, Perl does just that. Perl evaluates that only when this is true, making the form equivalent to the previous two examples. Likewise, the logical or works like the unless statement (or unless modifier). So, you can replace: unless (this) { that; } with this || that; Finally, the C-like ternary operator: exp1 ? exp2 : exp3; evaluates to exp2 if exp1 is true, and to exp3 in all other cases. You might have used: if (exp1) { exp2; } else { exp3; } but you could have eliminated all of that punctuation. For example, you could write:
($a < 10) ? ($b = $a) : ($a = $b); Which one should you use? Your choice depends on your mood, sometimes, or on how big each of the expression parts are, or on whether you need to parenthesize the expressions because of precedence conflicts. Look at other people's programs, and see what they do. You'll probably see a little of each. Larry suggests that you put the most important part of the expression first, so that it stands out.
Previous: 9.5 Expression Modifiers Learning Perl on Win32 Systems Book Index Next: 9.7 Exercises
9.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
9.7 Exercises
See Appendix A, Exercise Answers for the answers. 1. Extend the problem from the last chapter to repeat the operation until the word end is entered for one of the values. (Hint: use an infinite loop, and then do a last if either value is end.) 2. Rewrite the exercise from Chapter 4, Control Structures, summing numbers up to 999, using a loop that exits from the middle. (Hint: use a naked block with a redo at the end to get an infinite loop, and a last in the middle based on a condition.)
Previous: 9.6 &&, ||, and ?: as Control Structures Learning Perl on Win32 Systems Book Index Next: 10. Filehandles and File Tests
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 10
9.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
components. Another issue to consider is the use of long filenames versus the traditional MS-DOS 8.3 filename (a maximum of eight characters, followed by an optional extension of up to three characters). You'll find that some programs do not handle long filenames gracefully (particularly those with embedded spaces in them). In fact, if you're communicating with 16-bit programs (of either the Windows 3.x or DOS variety), the odds are very high that they won't understand long filenames. To convert a long filename to an 8.3 filename, use the Win32::GetShortPathName[4] function: [4] For a discussion of the Win32 extensions, see Appendix B, Libraries and Modules. use Win32; $longname = 'words.secret'; $shortname = Win32::GetShortPathName($longname); # $shortname has WORDS~1.SEC Perl can also be used to open files using UNC (Universal Naming Convention) pathnames. A UNC path consists of two backslashes (or slashes) followed by a machine name and a share. The following example opens a file using a UNC pathname: open(F, '//someserver/share/somefile') || die "open: $!"; $cnt = 0; while(<F>) {$cnt++;} # count the number of lines close(F) || die "close: $!"; print "$cnt lines\n"; If you use backslashes, make sure that they're properly escaped: open(F, "\\\\someserver\\share\\somefile") || die "open: $!"; $cnt = 0; while(<F>) {$cnt++;} # count the number of lines close(F) || die "close: $!"; print "$cnt lines\n";
Previous: 10.2 Opening and Closing a Filehandle Learning Perl on Win32 Systems Book Index Next: 10.4 A Slight Diversion: die
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
"open that file or die!" And that's an easy way to remember whether to use the logical and or logical or. The message at death (built from the argument to die) has the Perl program name and line number automatically attached, so you can easily identify which die was responsible for the untimely exit. If you don't like the line number or file revealed, make sure that the death text has a newline on the end. For example: die "you gravy-sucking pigs"; prints the file and line number, while die "you gravy-sucking pigs\n"; does not. Another handy thing inside die strings is the $! variable, which contains the text relating to the most recent operating system error value. The variable is used like this: open(LOG, ">>logfile") || die "cannot append: $!"; The program might end up saying "cannot append: Permission denied" as part of the message. There's also the close call function, which most people know as warn. It does everything die does, just short of actually dying. Use it to give error messages on standard error without a lot of extra hassle: open(LOG,">>log") || warn "discarding logfile output\n";
Previous: 10.3 Using Pathnames and Filenames Learning Perl on Win32 Systems Book Index Next: 10.5 Using Filehandles
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Table 10.1: File Tests and Their Meanings File Test Meaning -r -w -e -x -z -s -f -d -t -T -B -M -A -C File or directory is readable File or directory is writable File or directory exists File is executable File exists and has zero size (directories are never empty) File or directory exists and has nonzero size (the value is the size in bytes) Entry is a plain file Entry is a directory isatty on the filehandle is true (that is, the filehandle is a character device) File is text File is binary Modification age in days (C lang. time_t value) Access age in days (C lang. time_t value) Inode-modification age in days (C lang. time_t value)
Most of these tests return a simple true-false condition. A few don't, so let's talk about them. The -s operator does return true if the file is nonempty, but it's a particular kind of true. It's the length in bytes of the file, which evaluates as true for a nonzero number. The age operators -M, -A, and -C (yes, they're uppercase) return the number of days since the file was last modified, accessed, or had its information changed.[8] This age value is fractional with a resolution of one second: 36 hours is returned as 1.5 days. If you compare the age with a whole number (say three), you'll get only the files that were changed exactly that many days ago, not one second more or less. This means that you'll probably want a range comparison rather than an exact comparison to get files that are between three and four days old.[9] [8] The age is measured relative to the time the program started, as captured in C-library time into the $^T variable. You can get negative numbers for these ages if the queried value refers to an event that happened after the program began. [9] Or, you might want to use the int function. These operators can operate on filehandles as well as filenames. Giving a filehandle for the operand is all it takes. So to test whether the file opened as SOMEFILE is executable, you can use: if (-x SOMEFILE) {
# file open on SOMEFILE is executable } If you leave the filename or filehandle parameter off (that is, if you specify just -r or -s), the default operand is the file named in the $_ variable (there it is again!). So, to test a list of filenames to see which ones are readable, it's as simple as: foreach (@some_list_of_filenames) { print "$_ is readable\n" if -r; # same as -r $_ }
Previous: 10.5 Using Filehandles Learning Perl on Win32 Systems Book Index Next: 10.7 The stat Function
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Table 10.2: stat Return Valves Field dev ino mode nlink uid gid Description Device number (drive number) Inode number: 0 (zero) in Perl for Win32 File permission mode: read/write/execute Number of links to file (usually one for Win32 systems - NTFS filesystems may have a value greater than one) User ID - zero for Win32 Group ID - zero for Win32
Device Identifier (drive number) File size in bytes Last access time (C lang. time_t value)
mtime Last modification time (C lang. time_t value) ctime File creation time (C lang. time_t value)
blksize Disk block size (cluster size): zero for Win32 blocks Number of blocks for file: zero for Win32 Like the file tests, the operand of stat defaults to $_, meaning that the stat will be performed on the file named by the scalar variable $_. You can retrieve information about the filesystem of the current active drive using the Win32::FsType function: $fstype = Win32::FsType; if ($fstype =~ /NTFS/) { print "NTFS -- good choice!\n"; }
Previous: 10.6 The -x File Tests Learning Perl on Win32 Systems Book Index Next: 10.8 Exercises
10.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
10.8 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program to read in a filename from STDIN, and then open that file and display its contents with each line preceded by the filename and a colon. For example, if fred was read in, and the file fred consisted of the three lines aaa, bbb, and ccc, you would see fred: aaa, fred: bbb, and fred: ccc. 2. Write a program that prompts for an input filename, an output filename, a search pattern, and a replacement string, and then replaces all occurrences of the search pattern with the replacement string while copying the input file to the output file. Try it on some files. Can you overwrite an existing file? (Don't try it with anything important!) Can you use regular expression characters in the search string? Can you use $1 in the replacement string? 3. Write a program to read in a list of filenames and then display which of the files are readable, writable, and nonexistent. (You can perform each test for each filename as you read them, or you can perform the tests on the entire set of filenames after you've read them all. Don't forget to remove the newline at the end of each filename that you have read.) 4. Write a program to read in a list of filenames and then find the oldest file among them. Print out the name of the file and the age of that file in days.
Previous: 10.7 The stat Function Learning Perl on Win32 Systems Book Index Next: 11. Formats
11. Formats
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11
11. Formats
Contents: What Is a Format? Defining a Format Invoking a Format More About the Fieldholders The Top-of-Page Format Changing Defaults for Formats The FileHandle Module Exercises
10.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
$name The fieldholder is the @<<<<<<<<<<, which specifies a left-justified text field with 11 characters. More complete details about fieldholders will be given in the section called "More About the Fieldholders" later in this chapter. If the fieldline has multiple fieldholders, it needs multiple values, so the values are separated on the value line by commas: Hello, my name is @<<<<<<<<<< and I'm @<< years old. $name, $age Putting all this together, we can create a simple format for an address label: format ADDRESSLABEL = =============================== | @<<<<<<<<<<<<<<<<<<<<<<<<<< | $name | @<<<<<<<<<<<<<<<<<<<<<<<<<< | $address | @<<<<<<<<<<<<<<<<, @< @<<<< | $city, $state, $zip =============================== . Note that the lines of equal signs at the top and bottom of the format have no fields, and thus have no value lines following. (If you put a value line following such a fieldline, it will be interpreted as another fieldline, and will most likely not do what you want.) Whitespace within the value line is ignored. Some people choose to use additional whitespace in the value line to line up the variable with the fieldholder on the preceding line (such as putting $zip underneath the third field of the previous line in this example), but that's just for looks. Perl doesn't care, and the change doesn't affect your output. Text after the first newline in a value is discarded (except in the special case of multiline fieldholders, described later). A format definition is like a subroutine definition. It doesn't contain immediately executed code, and can therefore be placed anywhere in the file with the rest of the program - we tend to put ours toward the end of the file, ahead of my subroutine definitions.
Previous: 11.1 What Is a Format? Learning Perl on Win32 Systems Book Index Next: 11.3 Invoking a Format
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
In other words, the format is five colon-separated fields, which our code parses as described below. The while loop in the program reads each line of the address file, gets rid of the newline, and then splits the remainder into five variables. Note that the variable names are the same names as the ones we used when we defined the format. This fact, too, is important. After we have all of the variables loaded up (so that the values used by the format are correct), the write function invokes the format. Note that the parameter to write is the filehandle to be written to, and by default, the format of the same name is also used. Each field in the format is replaced with the corresponding value from the next line of the format. After the two sample records given above are processed, the file labels-to-print contains: =============================== | Stonehenge | | 4470 SW Hall Suite 107 | | Beaverton , OR 97005 | =============================== =============================== | Fred Flintstone | | 3737 Hard Rock Lane | | Bedrock , OZ 999bc | ===============================
Previous: 11.2 Defining a Format Learning Perl on Win32 Systems Book Index Next: 11.4 More About the Fieldholders
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
format MONEY = Assets: @<<<<<<<<< Liabilities @<<<<<<<< Net: @<<<<<<<<< pretty($assets,10), pretty($liab,9), pretty($assets-$liab,10) . sub pretty { my($n,$width) = @_; $width -= 2; # back off for negative stuff $n = sprintf("%.2f",$n); # sprintf is in later chapter if ($n < 0) { return sprintf("[%$width.2f]", -$n); # negative numbers get brackets } else { return sprintf(" %$width.2f ", $n); # positive numbers get spaces instead } } ## body of program: $assets = 32125.12; $liab = 45212.15; write (MONEY);
filled as best it can with the words from $comment spread over four lines. What happens if the complete text occupies less than four lines? Well, you'll get a blank line or two. This result is probably OK if you are printing out labels and need exactly the same number of lines for each entry to match them up with the labels. But if you are printing out a report, many blank lines merely use up your printer's paper budget. To fix this, use the suppression indicator. Any line that contains a tilde (~) character is suppressed (not output) if the line would have otherwise printed blank (just whitespace). The tilde itself always prints as a blank and can be placed anywhere a space could have been placed in the line. We could rewrite that last example as follows: format PEOPLE = Name: @<<<<<<<<<<<<< Comment: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $name, $comment ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $comment ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $comment ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $comment . Now, if the comment covers only two lines, the third and fourth lines are automatically suppressed. What if the comment is more than four lines? Well, we could make about 20 copies of the last two lines of that format, hoping that 20 lines will suffice. But that goes against the idea that Perl helps you to be lazy, so there's a lazy way to do it. Any line that contains two consecutive tildes will be repeated automatically until the result is a completely blank line. (The blank line is suppressed.) This changes our format to look like this: format PEOPLE = Name: @<<<<<<<<<<<<< Comment: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $name, $comment ~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $comment . This way, if the comment takes 1 line, 2 lines, or 20 lines, we are still OK. Note that the criterion for stopping the repeated line requires the line to be blank at some point. That means you probably don't want any constant text (other than blanks or tildes) on the line, or else the line will never become blank.
Previous: 11.3 Invoking a Format Learning Perl on Win32 Systems Book Index Next: 11.5 The Top-of-Page Format
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
The return value from select is a string containing the name of the previously selected handle. You can capture this value to restore the previously selected filehandle later, using code like this: $oldhandle = select LOGFILE; print "this goes to LOGFILE\n"; select ($oldhandle); # restore the previous handle Yes, for these examples, putting LOGFILE explicitly as the filehandle for the print is an easier method, but some operations require the currently selected filehandle to change, as we will soon see.
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
11.8 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 11 Formats
11.8 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that reads a file containing a list of lines composed of a user name, a company name, and an email address separated by colons. A sample line might look like this: John Doe:Foo Technologies:[email protected] Print out each field in formatted columns. Use format and write. 2. Add a top-of-page format to the previous program. (If your file is relatively short, you might need to set the pagelength to something like 10 lines so that you can get multiple instances of the top-of-page.) 3. Add a sequentially increasing page number to the top-of-page, so that you get page 1, page 2, and so on, in the output.
Previous: 11.7 The FileHandle Module Learning Perl on Win32 Systems Book Index Next: 12. Directory Access
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 12
Win32::GetCwd function. Every process[2] has its own current directory. When a new process is launched, it inherits its parent's current directory, but that's the end of the connection. If your Perl program changes its directory, the change won't affect the parent program that launched the Perl process. Likewise, the processes that the Perl program creates cannot affect that Perl program's current directory. The current directories for these new processes are inherited from the Perl program's current directory. [2] A process is the technical jargon for an executing program. The chdir function without a parameter defaults to taking you to your home directory, in imitation of a typical UNIX shell's cd command. The cd command in Windows NT does not normally work this way. In order to guess your home directory, Perl will check to see whether the HOME or LOGDIR environment variables are defined.
Previous: 11.8 Exercises Learning Perl on Win32 Systems Book Index Next: 12.2 Globbing
11.8 Exercises
12.2 Globbing
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
12.2 Globbing
The command prompt usually takes a solitary asterisk (*) command-line argument and turns it into a list of all of the filenames in the current directory. So, when you say del *, you'll remove all of the files from the current directory. (Don't try this unless you like restoring the current directory from your backup device.) Similarly, *.c as a command-line argument turns into a list of all filenames in the current directory that end in .c, and c:\temp\backup* is a list of all filenames in the directory c:\temp that begin with backup. (If this information is new to you, you probably want to read some more about using the command line somewhere else before proceeding.) The expansion of arguments like * or *.c into the list of matching filenames is called globbing. Perl supports globbing through a very simple mechanism - just put the globbing pattern between angle brackets or use the more mnemonically named glob function, like this: @a = <*.plx>; @a = glob("*.plx"); In a list context, as demonstrated here, the glob returns a list of all names that match the pattern or an empty list if none match. In a scalar context, the next name that matches is returned, or undef is returned if there are no more matches; this process is very similar to reading from a filehandle. For example, to look at one name at a time: while (defined($nextname = <c:/scripts/*.plx>)) { print "one of the files is $nextname\n"; } Here the returned filenames begin with c:\scripts\, so that if you want just the last part of the name, you'll have to whittle it down yourself, like so: while ($nextname = <c:/scripts/*.plx>) { $nextname =~ s#.*/##; # remove part before last slash print "one of the files is $nextname\n"; } Multiple patterns are permitted inside the file glob argument; the lists are constructed separately and then concatenated as if they were one big list: @fred_barney_files = <fred* barney*>; In other words, the glob returns the same values that an equivalent dir /B command with the same
parameters would return. Although file globbing and regular-expression matching function similarly, the meanings of their various special characters are quite different. Don't confuse the two, or you'll be wondering why <\.c$> doesn't find all of the files that end in .c! The argument to glob is variable interpolated before expansion. You can use Perl variables to select a wildcard based on a string computed at runtime: if (-d "c:/tmp") { $where = "c:/tmp"; } else { $where = "c:/temp"; } @files = <$where/*>; Here we set $where to be one of two different directory names, based on whether or not the directory c:\tmp exists.[3] We then get a list of files in the selected directory. Note that the $where variable is expanded, which means the wildcard to be globbed is either c:\tmp\* or c:\temp\*. [3] If we were really trying to find where the temporary directory was, we'd be checking the ENV hash for the TEMP variable: my $tmp = $ENV{'TEMP'} || $ENV{'TMP'}; There's one exception to this rule: the pattern <$var> (meaning to use the variable $var as the entire glob expression) must be written as <${var}> for reasons we'd rather not get into at this point.[4] [4] The construct <$fred> reads a line from the filehandle named by the contents of the scalar variable $fred. Together with some other features not covered in this book, this construct enables you to use indirect filehandles in which the name of a handle is passed around and manipulated as if it were data.
Previous: 12.1 Moving Around the Directory Tree Learning Perl on Win32 Systems Book Index Next: 12.3 Directory Handles
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
12.2 Globbing
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
12.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
12.6 Exercises
Answers are in Appendix A, Exercise Answers. 1. Write a program that changes the directory to a location specified as input, and then lists the names of the files found there in alphabetical order. (Don't show a list if the directory change doesn't succeed: merely warn the user.) 2. Modify the program to include all files, not just the ones that don't begin with dot. Try to do so with both a glob and a directory handle.
Previous: 12.5 Reading a Directory Handle Learning Perl on Win32 Systems Book Index Next: 13. File and Directory Manipulation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 13
The unlink function can take a list of names to be unlinked as well: unlink ("spottedowl","meadowlark"); # kill two birds unlink <*.bak>; # just like "del *.bak" in the command prompt The glob is evaluated in a list context, creating a list of filenames that match the pattern. This list is exactly what we need to feed unlink. The return value of unlink is the number of files successfully deleted. If only one argument exists, and it is deleted, the result is one; otherwise, the result is zero. If there are three filenames but only two could be deleted, the result is two. You can't tell which two, so if you need to figure out which deletion failed, you must do them one at a time. Here's how to delete all of the backup files (ending in .bak) while reporting an error for any file that cannot be deleted: foreach $file (<*.bak>) { # step through a list of .bak files unlink($file) || warn "having trouble deleting $file: $!"; } If unlink returns one (meaning the one file specified was indeed deleted), the true result skips the warn function. If the filename cannot be deleted, the zero result is false, so the warn is executed. Once again, this can be read abstractly as "unlink this file or tell me about it." If the unlink function is given no arguments, the $_ variable is once again used as a default. Thus, we could have written the preceding loop as: foreach (<*.bak>) { # step through a list of .bak files unlink || warn "having trouble deleting $_\: $!"; }
Previous: 12.6 Exercises Learning Perl on Win32 Systems Book Index Next: 13.2 Renaming a File
12.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Table 13.1: Key Values for File Permissions Mode Meaning 0666 0444 Read/Write Read only
Win32 systems determine whether or not a file is executable based on the file extension, so we're not going to worry about the execute bits. Furthermore, even though some Windows NT filesystems support advanced user/group rights, the current Perl implementation doesn't support access to these rights via chmod. The return value of chmod is the number of files successfully adjusted (even if the adjustment does nothing); so chmod works like unlink, and you should treat it as such with regard to error checking. Here's how to change the permissions of fred and barney while checking the errors for each: foreach $file ("fred","barney") { unless chmod (0666,$file) { warn "hmm... couldn't chmod $file.$!";
} } The Win32::File[2] extension module provides a way to access and set traditional DOS file attributes like the archive, system, and hidden attributes. This package consists of just two methods: GetAttributes and SetAttributes. Table 13.2 lists the attributes and their significations. [2] See Appendix B, Libraries and Modules, for an explanation of the Win32 extensions.
Table 13.2: DOS File Attributes and Their Significations Attribute ARCHIVE Explanation The file has been modified since it was last archived.
DIRECTORY The file is a directory. HIDDEN NORMAL The file is hidden (that is, it won't normally appear in directory listings). The file is a normal (read/write) file.
READONLY The file is read-only. SYSTEM The file is a system file (among other things, it can't be deleted without first changing the attributes).
To combine attributes, use the bitwise or operator |. Here's an example of how to make a file read-only, without changing its other attributes: use Win32::File; Win32::File::GetAttributes("foo.txt", $attrib) || die $!; Win32::File::SetAttributes("foo.txt", $attrib | READONLY) || die $!; Although we won't get to references until Chapter 18, CGI Programming, the $attrib is just that. For now, just know that upon returning from GetAttributes, $attrib will contain an attribute mask consisting of some combination of the values outlined above. To set user permissions on NTFS filesystems, use either the Win32::FileSecurity extension module, or the Windows NT cacls.exe program, which provides a command-line interface to file permissions.
Previous: 13.3 Making and Removing Directories Learning Perl on Win32 Systems Book Index Next: 13.5 Modifying Timestamps
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
13.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
13.6 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program that works like del, deleting the files given as command-line arguments when the program is invoked. (You don't need to handle any options of del.) Be careful to test this program in a mostly empty directory so that you don't accidentally delete useful stuff! Remember that the command-line arguments are available in the @ARGV array when the program starts. 2. Write a program that works like rename, renaming the first command-line argument to the second command-line argument. (You don't need to handle any options of rename, or more than two arguments.) You may wish to consider how to handle the rename when the destination is a directory.
Previous: 13.5 Modifying Timestamps Learning Perl on Win32 Systems Book Index Next: 14. Process Management
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 14
This time, we not only send the output of the dir command into a file with a redirection to the new command shell, but also check the return status. If the return status is true (nonzero), something went wrong with the shell command, and the die function will do its deed. This is backwards from normal Perl operator convention - a nonzero return value from the system operator generally indicates that something went wrong. You can feed anything to the system function that you can feed to your command shell. Here's an example of generating a dir command and sending the output to a filename specified by a Perl variable: $where = "dir_out.".++$i; # get a new filename system "dir >$where"; The double-quoted string is variable interpolated, so Perl replaces $where with its value. In addition to the standard filehandles, the current directory and the environment variables are inherited by the child. These variables are typically created by the command shell set command and accessed or altered using the %KEYNAME% construct. Environment variables are used by many utilities, including the command shell itself, to alter or control the way that utility operates. Perl gives you a way to examine and alter current environment variables through a special hash called %ENV (uppercase). Each key of this hash corresponds to the name of an environment variable, with the corresponding value being, well, the corresponding value. Examining this hash shows you the environment handed to Perl by the parent process - altering the array affects the environment used by Perl and by its children processes, but not that of its parents. For example, here's a simple program that prints out all of your environment variables: foreach $key (sort keys %ENV) { print "$key=$ENV{$key}\n"; } Note that the equal sign here is not an assigment, but simply a text character that the print function is using to say stuff like USERNAME=eriko or COMSPEC=c:\nt\system32\cmd.exe. Here's a program snippet that alters the value of PATH to make sure that the nmake command run by system is looked for only in the correct places: $oldPATH = $ENV{"PATH"}; # save previous path $ENV{"PATH"} = "c:\\msdev\\bin;c:\\winnt;c:\\winnt\\system32"; # force known path system("nmake myproj.mak >output"); # run command $ENV{"PATH"} = $oldPATH; # restore previous path That's a lot of typing. It'd be faster just to set a local value for this hash element. Despite its other shortcomings, the local operator can do one thing that my cannot: it can give just one element of an array or a hash a temporary value. For example: { local $ENV{"PATH"} = "c:\\msdev\\bin;c:\\winnt;c:\\winnt\\system32";
system("nmake fred bedrock >output"); } The system function can also take a list of arguments rather than a single argument. In this case, rather than handing the list of arguments off to a command shell, Perl treats the first argument as the command to run (located according to the PATH if necessary) and the remaining arguments as arguments to the command without normal shell interpretation. In other words, you don't need to quote whitespace or worry about arguments that contain angle brackets because those are all merely characters to hand to the program. So, the following two commands are equivalent: system "nmake 'fred flintstone.mak' buffaloes"; # using command shell system "nmake","fred flintstone.mak","buffaloes"; # using list Giving system a list rather than giving it a simple string saves one command shell process as well, so do this when you can. (In fact, when the one-argument form of system is simple enough, Perl itself optimizes away the shell invocation entirely, calling the resulting program directly as if you had used the multiple-argument invocation.) Here's another example of equivalent forms: @cfiles = ("fred.c","barney.c"); @options = ("-DHARD","-DGRANITE"); system "cc -o slate @options @cfiles"; system "cc","-o","slate",@options,@cfiles;
Previous: 13.6 Exercises Learning Perl on Win32 Systems Book Index
# # # #
13.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
The exit function causes an immediate exit from the current Perl process. You'd use this to abort a Perl program from somewhere in the middle. The exit function takes an optional parameter, which serves as the numeric exit value that can be noticed by the parent process. The default is to exit with a zero value, indicating that everything went OK.
Previous: 14.2 Using Backquotes Learning Perl on Win32 Systems Book Index Next: 14.4 Summary of Process Operations
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Table 14.1: Summary of Subprocess Operations Operation system() Backquoted string open() command as filehandle for output open() command as filehandle for input Standard Input Inherited from program Inherited from program Connected to filehandle Standard Output Inherited from program Captured as string value Inherited from program Standard Error Inherited from program Inherited from program Inherited from program Waited for? Yes Yes Only at time of close()
Connected to filehandle
Not implemented
Not implemented
Not implemented
The simplest way to create a process is with the system function. Standard input, output, and error are unaffected (they're inherited from the Perl process). A backquoted string creates a process, capturing the standard output of the process as a string value for the Perl program. Standard input and standard error are unaffected. Both methods require that the process finish before any more code is executed. A simple way to get an asynchronous process (one that allows the Perl program to continue before the process is complete) is to open a command as a filehandle, creating a pipe for the command's standard input or standard output. A command opened as a filehandle for reading inherits the standard input and standard error from the Perl program; a command opened as a filehandle for writing inherits the standard output and standard error from the Perl program.
14.5 Win32::Process
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
14.5 Win32::Process
The most flexible way of starting a process on Windows NT is to use the Win32::Process module.[3] Using this module, you can select whether or not you want to wait for the child process to run to completion, configure priorities, and suspend or resume processes. [3] Of course, this method won't work at all on non-Windows platforms. Even though we haven't covered all of the relevant concepts, we are going to run through a Win32::Process example. As shown, the Win32::Process module contains a method (subroutine) called Create that does all the work of creating a process: use Win32::Process; Win32::Process::Create($Process, "c:\\nt\\system32\\notepad.exe", "notepad", 0, DETACHED_PROCESS, ".") || die "Create: $!"; This code creates an asychronous instance of Notepad. Let's take a look at the parameters. The first parameter $Process is a scalar reference that receives the process object if the call succeeds. We'll discuss references in Chapter 18, CGI Programming, but for now, you can just think of it as a parameter that receives output. The second argument is a fully qualified (system-dependent) path to the executable. The third argument is the command line passed to the program. In this case, we're just invoking Notepad without any documents or options. The next argument specifies whether or not the new process inherits handles from the parent process (the Perl program). A value of one indicates that the process inherits any inheritable open handle in the parent process. Inheritable handles include I/O handles, socket handles, synchronization handles, and so on. Unless you really know what you're doing here, you're better off specifying this value as zero. The next argument specifies various create options for the new process. The flag that we've passed is DETACHED_PROCESS, which indicates that the new process does not have access to the console of the calling process (our Perl program). Other flags that you may be interested in include
CREATE_SUSPENDED, which creates a process that is initially suspended, and CREATE_SEPARATE_WOW_VDM, which runs a 16-bit process in its own Virtual DOS Machine (VDM). For more information on the various options, see the win32mod documentation for Win32::Process.
Previous: 14.4 Summary of Process Operations Learning Perl on Win32 Systems Book Index Next: 14.6 Exercises
14.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
14.6 Exercises
1. Write a program that takes two directory arguments and then uses the xcopy command to copy the first directory (and all related subdirectories) to the second directory. 2. Write a program that uses the Windows NT net view command to list all hosts in your domain or workgroup, in sorted order.
Previous: 14.5 Win32::Process Learning Perl on Win32 Systems Book Index Next: 15. Other Data Transformation
14.5 Win32::Process
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 15
Notice that both the string being searched and the string being searched for can each be a literal string, a scalar variable containing a string, or even an expression that has a string value. Here are some more examples: $which = index("a very long string","long"); # $which gets 7 $which = index("a very long string","lame"); # $which gets -1
If the string contains the substring at more than one location, the index function returns the leftmost location. To find later locations, you can give index a third parameter. This parameter is the minimum value that will be returned by index, allowing you to look for the next occurrence of the substring that follows a selected position. This index looks like this: $x = index($bigstring,$littlestring,$skip); Here are some examples of how this third parameter works: $where = index("hello world","l"); # returns 2 (first l) $where = index("hello world","l",0); # same thing $where = index("hello world","l",1); # still same $where = index("hello world","l",3); # now returns 3 # (3 is the first place greater than or equal to 3) $where = index("hello world","o",5); # returns 7 (second o) $where = index("hello world","o",8); # returns -1 (none after 8) Going the other way, you can scan from the right to get the rightmost occurrence using rindex. The return value is still the number of characters between the left end of the string and the start of the substring, as before, but you'll get the rightmost occurrence instead of the leftmost occurrence if there are more than one. The rindex function also takes a third parameter like index does, so that you can get an occurrence that is less than or equal to a selected position. Here are some examples of what you get: $w = rindex("hello world","he"); # $w gets 0 $w = rindex("hello world","l"); # $w gets 9 (rightmost l) $w = rindex("hello world","o"); # $w gets 7 $w = rindex("hello world","o "); # now $w gets 4 $w = rindex("hello world","xx"); # $w gets -1 (not found) $w = rindex("hello world","o",6); # $w gets 4 (first before 6) $w = rindex("hello world","o",3); # $w gets -1 (not found before 3)
Previous: 14.6 Exercises Learning Perl on Win32 Systems Book Index Next: 15.2 Extracting and Replacing a Substring
14.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
of a huge number for that argument by pioneer Perl programmers. You may come across such cases in your Perl archeological expeditions. If the first argument to substr is a scalar variable (in other words, it could appear on the left side of an assignment operator), then the substr itself could appear on the left side of an assignment operator. This case may look strange if you come from a C background, but if you've ever played with some dialects of BASIC, it's quite normal. What gets changed as the result of such an assignment is the part of the string that would have been returned had the substr been used on the right-hand side of the expression instead. In other words, substr($var,3,2) returns the fourth and fifth characters (starting at 3, for a count of 2), so assigning a value to substr($var,3,2) changes those two characters as shown: $hw = "hello world!"; substr($hw, 0, 5) = "howdy"; # $hw is now "howdy world!" The length of the replacement text (what gets assigned into the substr) doesn't have to be the same as the text it is replacing, as shown in this example. The string will automatically grow or shrink as necessary to accommodate the text. Here's an example in which the string gets shorter: substr($hw, 0, 5) = "hi"; # $hw is now "hi world!" and here's an example that makes the string longer: substr($hw, -6, 5) = "nationwide news"; # replaces "world" The shrinking and growing are fairly efficient, so don't worry about using them arbitrarily, although replacing a string with a string of equal length is a faster solution.
Previous: 15.1 Finding a Substring Learning Perl on Win32 Systems Book Index Next: 15.3 Formatting Data with sprintf( )
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Let's look through this routine. If the value of $a is less than (numerically in this case) the value of $b, we return a -1 value. If the values are numerically equal, we get back a 0, and otherwise a 1. So, according to our specification for a sort comparison routine, this method should work. How do we use it? Let's try sorting the following list: @somelist = (1,2,4,8,16,32,64,128,256); If we use the ordinary sort without any adornment on the list, we get the numbers sorted as if they were strings, and in their ASCII order, like so: @wronglist = sort @somelist; # @wronglist is now (1,128,16,2,256,32,4,64,8) This sort is certainly not very numeric. Well, let's give sort our newly defined sort routine. The name of the sort routine immediately follows the sort keyword, like so: @rightlist = sort by_number @wronglist; # @rightlist is now (1,2,4,8,16,32,64,128,256) This sort does the trick. Note that you can read the sort with its companion sort routine in a human-like fashion: "sort by number." This feature is why we named the subroutine with a by_ prefix. This kind of three-way value of -1, 0, and +1 on the basis of a numeric comparison occurs often enough in sort routines that Perl has a special operator to do this in one fell swoop. The operation is often called the spaceship operator, and looks like <=>. Using the spaceship operator, the preceding sort subroutine can be replaced with this: sub by_number { $a <=> $b; } Note the spaceship between the two variables. Yes, it is indeed a three-character-long operator. The spaceship returns the same values as the if/elsif chain from the previous definition of this routine. Now this is pretty short, but you can reduce the sort invocation even further, by replacing the name of the sort routine with the entire sort routine in line, like so: @rightlist = sort { $a <=> $b } @wronglist; There are some who argue that this shortcut decreases readability. They are wrong. Others argue that it removes the need to go somewhere else for the definition. Perl doesn't care. Our personal rule is that if it doesn't fit on one line or we have to use it more than once, it goes into a subroutine. The spaceship operator for numeric comparison has a comparable string operator called cmp. The cmp operator returns one of three values depending on the relative string comparisons of the two arguments. So, another way to write the default sort order[2] is: [2] This statement is not exactly true. The built-in sort discards undef elements, but this one doesn't. @result = sort { $a cmp $b } @somelist; You probably won't ever write this exact subroutine (mimicking the built-in default sort), unless you're
writing a book about Perl. However, the cmp operator does have its uses in the construction of cascaded ordering schemes. For example, you might need to put the elements in numeric order unless they're numerically equal, in which case they should go in ASCII string order. (By default, the by_number routine above just sticks nonnumeric strings in some random order because there's no numeric ordering when comparing two values of zero.) Here's a way to say "numeric, unless they're numerically equal, then string": sub by_mostly_numeric { ($a <=> $b) || ($a cmp $b); } How does this work? Well, if the result of the spaceship is -1 or 1, the rest of the expression is skipped, and the -1 or 1 is returned. If the spaceship evaluates to zero, however, the cmp operator gets its turn at bat, returning an appropriate ordering value considering the values as strings. The values being compared are not necessarily the values being passed in. For example, say you have a hash where the keys are the login names and the values are the real names of each user. Suppose you want to print a chart where the login names and real names are sorted in the order of the real names. How would you do that? Actually, the solution is fairly easy. Let's assume the values are in the array %names. The login names are thus the list of keys(%names). What we want to end up with is a list of the login names sorted by the corresponding value, so for any particular key $a, we need to look at $names{$a} and sort based on that. If you think of the sort that way, it almost writes itself, as in: @sortedkeys = sort by_names keys(%names); sub by_names { return $names{$a} cmp $names{$b}; } foreach (@sortedkeys) { print "$_ has a real name of $names{$_}\n"; } To this we should also add a fallback comparison. Suppose the real names of two users are identical. Because of the whimsical nature of the sort routine, we might get one value ahead of another the first time through and the values in the reversed order the next time. This difference is bad if the report might be fed into a comparison program for reporting, so try very hard to avoid such things. With the cmp operator, you can avoid this case like this: sub by_names { ($names{$a} cmp $names{$b}) || ($a cmp $b); } Here, if the real names are the same, we sort based on the login name instead. Because the login name is guaranteed to be unique (after all, login names are the keys of this hash, and no two keys are the same), then we can ensure a unique and repeatable order. Good defensive programming during the day is better than a late-night call from a system administrator wondering why the security alarms are going off.
15.5 Transliteration
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
15.5 Transliteration
When you want to take a string and replace every instance of some character with some new character, or delete every instance of some character, you can do so with carefully selected s/// commands. But suppose you had to change all of the a's into b's, and all of the b's into a's? You can't do that with two s/// commands because the second one would undo all of the changes that the first one made. Perl provides a tr operator that does the trick: tr/ab/ba/; The tr operator takes two arguments: an old string and a new string. These arguments work like the two arguments to s///; in other words, there's some delimiter that appears immediately after the tr keyword that separates and terminates the two arguments (in this case, a slash, but nearly any character will do). The tr operator modifies the contents of the $_ variable (just like s///), looking for characters of the old string within the $_ variable. All such characters found are replaced with the corresponding characters in the new string. Here are some examples: $_ = "fred and barney"; tr/fb/bf/; # $_ is now "bred and farney" tr/abcde/ABCDE/; # $_ is now "BrED AnD fArnEy" tr/a-z/A-Z/; # $_ is now "BRED AND FARNEY" Notice how a range of characters can be indicated by two characters separated by a dash. If you need a literal dash in either string, precede it with a backslash. If the new string is shorter than the old string, the last character of the new string is repeated enough times to make the strings equal length, like so: $_ = "fred and barney"; tr/a-z/x/; # $_ is now "xxxx xxx xxxxxx" To prevent this behavior, append a d to the end of the tr/// operator, which means delete. In this case, the last character is not replicated. Any character that matches in the old string without a corresponding character in the new string is simply removed from the string. For example: $_ = "fred and barney"; tr/a-z/ABCDE/d; # $_ is now "ED AD BAE"
Notice how any letter after e disappears because there's no corresponding letter in the new list, and that spaces are unaffected because they don't appear in the old list. If the new list is empty and there's no d option, the new list is the same as the old list. This default may seem silly. Why replace an I for an I and a 2 for a 2? But the command actually does something useful. The return value of the tr/// operator is the number of characters matched by the old string, and by changing characters into themselves, you can get the count of that kind of character within the string.[3] For example: [3] This method works only for single characters. To count strings, use the /g flag to a pattern match: while (/pattern/g) { $count++; } $_ = "fred and barney"; $count = tr/a-z//; # $_ unchanged, but $count is 13 $count2 = tr/a-z/A-Z/; # $_ is uppercased, and $count2 is 13 If you append a c (like appending the d), you complement the old string with respect to all 256 characters. Any character you list in the old string is removed from the set of all possible characters; the remaining characters, taken in sequence from lowest to highest, form the resulting old string. So, a way to count or change the nonletters in our string could be: $_ = "fred and barney"; $count = tr/a-z//c; # $_ unchanged, but $count is 2 tr/a-z/_/c; # $_ is now "fred_and_barney" (non-letters => _) tr/a-z//cd; # $_ is now "fredandbarney" (delete non-letters) Notice that the options can be combined, as shown in that last example, where we first complement the set (the list of letters become the list of all nonletters) and then use the d option to delete any character in that set. The final option for tr/// is s, which squeezes multiple consecutive copies of the same resulting translated letter into one copy. As an example, look at this: $_ = "aaabbbcccdefghi"; tr/defghi/abcddd/s; # $_ is now "aaabbbcccabcd" Note that the def became abc, and ghi (which would have become ddd without the s option) becomes a single d. Also note that the consecutive letters at the first part of the string are not squeezed because they didn't result from a translation. Here are some more examples: $_ = "fred and barney, wilma and betty"; tr/a-z/X/s; # $_ is now "X X X, X X X" $_ = "fred and barney, wilma and betty"; tr/a-z/_/cs; # $_ is now "fred_and_barney_wilma_and_betty" In the first example, each word (consecutive letters) was squeezed down to a single letter X. In the second example, all chunks of consecutive nonletters became a single underscore.
Like s///, the tr operator can be targeted at another string besides $_ using the =~ operator: $names = "fred and barney"; $names =~ tr/aeiou/X/; # $names now "frXd Xnd bXrnXy"
Previous: 15.4 Advanced Sorting Learning Perl on Win32 Systems Book Index Next: 15.6 Exercises
15.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
15.6 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a program to read a list of filenames, breaking each name into its head and tail components. (Everything up to the last backslash is the head, and everything after the last slash is the tail. If there's no backslash, everything is in the tail.) Try this exercise with things like \fred, barney, and fred\barney. Do the results make sense? 2. Write a program to read in a list of numbers on separate lines, and then sort them numerically, printing out the resulting list in a right-justified column. (Hint: the format to print a right-justified column is something like "%20g".) 3. Create a file that consists of sentences, one per line. Write a program that makes the first character of each sentence uppercase, and the rest of the sentence lowercase. (Does the program work even when the first character is not a letter? How would you alter the program if the sentences were not already one per line?)
Previous: 15.5 Transliteration Learning Perl on Win32 Systems Book Index Next: 16. System Information
15.5 Transliteration
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 16
print "The homedir for $username is $homedir\n"; For more information on using Win32::NetAdmin, explore the win32mod documentation. As you explore Perl scripts on the Net, you'll no doubt find scripts that refer to any of a myriad of Perl functions that access UNIX password and group files. At the time of this writing, these functions are not implemented in Perl on Win32 platforms, but you can usually duplicate the functionality (if it's applicable) using one of the Win32 extension modules.
Previous: 15.6 Exercises Learning Perl on Win32 Systems Book Index Next: 16.2 Packing and Unpacking Binary Data
15.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
The exact list of the various pack formats is given in the reference documentation (perlfunc, or Programming Perl). You'll see a few here as examples, but we're not going to list them all. What if you were given the eight-byte string ABCDEFGH and were told that it was really the memory image (one character is one byte) of two long (four-byte) signed values? How would you interpret it? Well, you'd need to do the inverse of pack, called unpack. This function takes a format control string (usually identical to the one you'd give pack) and a data string, and returns a list of values that make up the memory image defined in the data string. For example, let's take that string apart: ($val1,$val2) = unpack("ll","ABCDEFGH"); This statement gives us back something like 0x41424344 for $val1, or possibly 0x44434241 instead (depending on big-endian-ness). In fact, by the values that come back, we can determine if we are on a little- or big-endian machine. Whitespace in the format control string is ignored, and can be used for readability. A number in the format control string generally repeats the previous specification that many times. For example, CCCC can also be written C4 or C2C2 with no change in meaning. (A few of the specifications use a trailing number as a part of the specification, and thus cannot be multiplied in this manner.) A format character can also be followed by a *, which repeats the format character enough times to swallow up the rest of the list or the rest of the binary image string (depending on whether you are packing or unpacking). So, another way to pack four unsigned characters into a string is: $buf = pack("C*", 140, 186, 65, 25); The four values here are swallowed up by the one format specification. If you had wanted two short integers followed by "as many unsigned chars as possible," you could say something like: $buf = pack("s2 C*", 3141, 5926, 5, 3, 5, 8, 9, 7, 9, 3, 2); Here, we take the first two values as shorts (generating four or eight characters, probably) and the remaining nine values as unsigned characters (generating nine characters, almost certainly). Going in the other direction, unpack with an asterisk specification can generate a list of elements of unpredetermined length. For example, unpacking with C* creates one list element (a number) for each string character. Therefore, this statement: @values = unpack("C*", "hello, world!\n"); yields a list of 14 elements, one for each of the characters of the string.
Previous: 16.1 Getting User and Machine Information Learning Perl on Win32 Systems Book Index Next: 16.3 Getting Network Information
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
($addr) = (gethostbyname("slate.bedrock.com"))[4]; print "Slate's address is ", join(".",unpack("C4", $addr)), "\n"; The unpack takes the four-byte string and returns four numbers. This just happens to be in the right order for the join to glue in a dot between each pair of numbers to make the human-readable form. See Appendix C, Networking Clients, for information about building simple networking clients.
Previous: 16.2 Packing and Unpacking Binary Data Learning Perl on Win32 Systems Book Index Next: 16.4 The Registry
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Table 16.1 details the four main subtrees of the Registry, and a general description of what each one is used for. Table 16.1: Sample Registry Subtrees Registry Subtree Description
HKEY_LOCAL_MACHINE Contains information about the local computer, including information about the hardware and operating system HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_USERS Contains OLE and file association information Contains user profile information for the currently logged-on user including environment, desktop, and preference settings Contains all actively loaded user profiles (including HKEY_CURRENT_USER) and default user profile information
The Win32:Registry package creates an instantiated registry key object[2] for each of these subtrees, so you can open keys relative to these trees. [2] See Chapter 18, CGI Programming, for a discussion of Perl objects. The Registry can contain several different data types including strings, dwords (unsigned four-byte integers), unicode strings, expanding strings (e.g., environment variables that rely on the value of another environment variable), binary data, and more. Win32::Registry defines constants (in the form of subroutines) for these values. Table 16.2 gives some of the most useful constants.
Table 16.2: Win32::Registry Constants Win32::Registry Constant Data Type REG_SZ REG_DWORD REG_MULTI_SZ REG_EXPAND_SZ REG_BINARY
Previous: 16.3 Getting Network Information
String Data Unsigned four-byte integer Multiple strings, delimited with NULL Strings that expand (e.g., based on environment variables) Binary data (no particular format is assumed)
Learning Perl on Win32 Systems Book Index Next: 16.5 Opening and Reading Registry Values
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
method succeeds, $CurrVer will contain the Registry object corresponding to the CurrentVersion key. Line four uses the $CurrVer key to call the GetValues method. GetValues takes a reference to a hash as a parameter and populates that hash with all of the values under $CurrVer. Each hash element consists of a key with the name of the Registry value and a value containing a reference to a three-element list. The list contains the value name, the data type of the value, and the value data. The remaining lines of the example iterate over each value using the foreach operator and print its value name and data value. For example: foreach $k (keys %vals) { # iterate over keys $key = $vals{$k}; # get ref to list print "$$key[0] = $$key[2]\n"; # dereference as list } We've seen how the Open method will open a Registry key relative to one of the main subtrees (or another key). We can also use the Create method to open a key, creating it if it doesn't exist. Create won't create more than one level deep, so we need to have a handle to the parent key before calling create. Here's an example that creates a new key under the HKEY_CURRENT_USER\SOFTWARE hive: use Win32::Registry; $main::HKEY_CURRENT_USER->Open("SOFTWARE", $Software) || die "Open: $!"; $Software->Create("ERIKO", $eriko) || die "Create: $!"; # new key is in $eriko In order to create a key under SOFTWARE, we first need to obtain the key to SOFTWARE. We do so by using Open again, this time with the HKEY_CURRENT_USER subtree. After we have the SOFTWARE key open, we can create keys directly beneath it.
Previous: 16.4 The Registry Learning Perl on Win32 Systems Book Index Next: 16.6 Setting Registry Values
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
This code assumes that none of the child keys of blah have child keys themselves. If they do, you'll need to do something recursive to iterate over each subkey and all of its subkeys. The following example saves a Registry hive to an external file using the Save method: use Win32::Registry; $main::HKEY_LOCAL_MACHINE->Open("SOFTWARE", $Software) || die "Open: $!"; $Software->Open("ActiveState", $ActiveState) || die "Open: $!"; # write ActiveState hive to perlkeys.reg $ActiveState->Save("perlkeys.reg") || die "Save: $!"; You can connect to the Registry of a remote machine (but only to the HKEY_LOCAL_MACHINE or HKEY_USERS hives) using the RegConnectRegistry function: use Win32::Registry; Win32::Registry::RegConnectRegistry("\\\\somemachine", HKEY_LOCAL_MACHINE, $key) || die "connect: $!";
Previous: 16.5 Opening and Reading Registry Values Learning Perl on Win32 Systems Book Index Next: 16.7 Exercises
16.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
16.7 Exercises
See Appendix A, Exercise Answers for the answers. 1. Write a program that takes a machine name as input and then prints a list of all of the IP addresses for that machine (skip this example if you don't have TCP/IP installed). Try your program on something like www.microsoft.com that has lots of IP addresses to make sure you get it right. 2. Write a program that takes as an argument a single Registry key relative to HKEY_LOCAL_MACHINE and prints all of the values under it (don't worry about recursing into child keys or about binary data for now, just print whatever you get). 3. Write a subroutine that creates all of the keys in a path if they don't exist. To make things easier, pass in the subtree to which the path is relative. 4. Using what you know about unpack, write a routine that will print a hexidecimal representation of a REG_DWORD value (that is, a four-byte integer value).
Previous: 16.6 Setting Registry Values Learning Perl on Win32 Systems Book Index Next: 17. Database Manipulation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 17
The size, number, and kind of keys and values in a DBM database are restricted, and depending on which version of DBM library you're using, a DBM array may share these same restrictions. Perl for Win32 includes the SDBM database routines. In general, if you keep both the keys and the values down to 1000 arbitrary binary characters or less, you'll probably be OK.
Previous: 16.7 Exercises Learning Perl on Win32 Systems Book Index Next: 17.2 Opening and Closing DBM Hashes
16.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Opening a disk file for both reading and writing, and setting the filehandle to binary mode Moving around in this file to an arbitrary position Fetching data by a length rather than up to the next newline Writing data down in fixed-length blocks
The open function takes an additional plus sign before its I/O direction specification to indicate that the file is really being opened for both reading and writing. For example: open(A,"+<b"); # open file b read/write (error if file absent) open(C,"+>d"); # create file d, with read/write access open(E,"+>>f"); # open or create file f with read/write access Notice that all we've done was to prepend a plus sign to the I/O direction. Next, we need to set the filehandle to binary mode using the binmode function: binmode(A); # set the filehandle to binary mode Some operating systems don't need to use binmode, so you may find scripts that don't do this. Windows NT (and Windows 95) systems do need to use binmode, so if you find yourself getting strange results while using a random-access database file, this is the first place you should check. After we've got the file open, we need to move around in it. You do this with the seek function, which
takes the same three parameters as the C fseek library routine. The first parameter is a filehandle; the second parameter gives an offset, which is interpreted in conjunction with the third parameter. Usually, you'll want the third parameter to be zero so that the second parameter selects a new absolute position for the next read from or write to the file. For example, to go to the fifth record on the filehandle NAMES (as described above), you can do this: seek(NAMES,4*83,0); After the file pointer has been repositioned, the next input or output will start there. For output, use the print operator, but be sure that the data you are writing is the right length. To obtain the right length, we can call upon the pack() operator: print NAMES pack("A40 A A40 s", $first, $middle, $last, $age); That pack() specifier gives 40 characters for $first, a single character for $middle, 40 more characters for $last, and a short (two bytes) for the $age. This should be 83 bytes long, and will be written at the current file position. Last, we need to fetch a particular record. Although the <NAMES> operator returns all of the data from the current position to the next newline, that's not correct; the data is supposed to go for 83 bytes, and there probably isn't a newline right there. Instead, we use the read function, which looks and works a lot like its C language counterpart: $count = read(NAMES, $buf, 83); The first parameter for read is the filehandle. The second parameter is a scalar variable that holds the data that will be read. The third parameter gives the number of bytes to read. The return value from read is the number of bytes actually read; typically, this number is the same number as the number of bytes asked for unless the filehandle is not opened or you are too close to the end of the file. After you have the 83-character data, break the data into its component parts with the unpack operator: ($first, $middle, $last, $age) = unpack("A40 A A40 s", $buf); Note that the pack and unpack format strings are the same. Most programs store this string in a variable early in the program, and even compute the length of the records using pack instead of sprinkling the constant 83 everywhere: $names = "A40 A A40 s"; $names_length = length(pack($names)); # probably 83
Previous: 17.3 Using a DBM Hash Learning Perl on Win32 Systems Book Index Next: 17.5 Variable-Length ( Text) Databases
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Here's a way to change everyone's login name to lowercase in some file that contains a list of user logins, one per line: @ARGV = ("userlist.txt"); # prime the diamond operator $^I = ".bak"; # write userlist.bak for safety while (<>) { # main loop, once for each line tr/A-Z/a-z/; # change everything to lower case print; # send output to ARGVOUT: the new userlist.txt } As you can see, this program is pretty simple. In fact, the same program can be generated entirely with a few command-line arguments: perl -p -i.bak -e 'tr/A-Z/a-z/' userlist.txt The -p switch brackets your program with a while loop that includes a print statement. The -i switch sets a value into the $^I variable. The -e switch defines the following argument as a piece of Perl code for the loop body. The final argument gives an initial value to @ARGV. Command-line arguments are discussed in greater detail in Programming Perl or the perlrun documentation.
Previous: 17.4 Fixed-Length Random-Access Databases Learning Perl on Win32 Systems Book Index Next: 17.6 Win32 Database Interfaces
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
17.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
17.7 Exercises
See Appendix A, Exercise Answers for answers. 1. Create two programs: one program that reads the data from <>, splits the data into words, and then updates a DBM file noting the number of occurrences of each word; and another program to open the DBM file and display the results sorted by descending count. Run the first program on a few files and see if the second program picks up the proper counts.
Previous: 17.6 Win32 Database Interfaces Learning Perl on Win32 Systems Book Index Next: 18. CGI Programming
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 18
introductory knowledge about references, library modules, and object-oriented programming with Perl as we go along. Then, at the end, we'll make a quick survey of Perl's usefulness for other sorts of web programming. As a standalone tutorial, this chapter (and most any other document shorter than a couple of hundred pages) will not be adequate to teach the more complex topics touched on here, such as object programming and the use of references. But as a means to gain a preliminary taste of what's ahead of you, the examples presented here, together with their explanations, may whet your appetite and give you some practical orientation as you slog through the appropriate textbooks. And if you're the learn-by-doing type, you'll actually start writing useful programs based on the models you find here. We assume you already possess a basic familiarity with HTML.
17.7 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Each text-input field on the form has a name (given in the form's HTML code), and an associated value, which is whatever you type into the field. The form itself is associated (via the HTML <FORM> tag) with a CGI program that processes the form input. When you fill out the form and click on Submit, the browser accesses the URL of the CGI program. But first it tacks onto the end of the URL a query string consisting of one or more name=value pairs; each name is the name of a text input field, and each value is the corresponding input you provided. So the URL to which the browser submits your form input looks something like this (where the query string is everything after the question mark): http://www.SOMEWHERE.org/cgi-bin/some_cgi_prog?flavor=vanilla&size=double In this case, there are two name=value pairs. Such pairs are separated by an ampersand (&): a detail you won't have to worry about when you use the CGI.pm module. The part of the URL that reads /cgi-bin/some_cgi_prog/ will receive further explanation later; at the moment, you need only note that this part provides a path to the CGI program that will process the HTML form input. When the web server (www.SOMEWHERE.org in this case) receives the URL from your browser, it invokes the CGI program, passing the name=value pairs to the program as arguments. The program then does whatever it does, and (usually) returns HTML code to the server, which in turn downloads the code to the browser for display to you. The conversation between the browser and the server, and also between the server and the CGI program, follows the protocol known as HTTP. You needn't worry much about this when writing your CGI program, because CGI.pm takes care of the protocol requirements for you. The way in which the CGI program expects to receive its arguments (and other information) from the browser via the server is governed by the CGI specification. Again, you don't need to worry too much about this; as you will see, CGI.pm automatically unpacks the arguments for you. Finally, you should know that CGI programs can work with any HTML document, not just forms. For example, you could write the HTML code: Click <a href="http://www.SOMEWHERE.org/cgi-bin/fortune.cgi">here</a> to receive your fortune. In this case, there wouldn't be any argument supplied to the CGI program with the URL. Or the HTML document could give two links for the user to click on - one to receive a fortune, and one to receive the current date. Both links could point to the same program, in one case with the argument fortune following the question mark in the URL, and in the other case with the argument date. The HTML links would look like this: <a href="http://www.SOMEWHERE.org/cgi-bin/fortune_or_date?fortune> <a href="http://www.SOMEWHERE.org/cgi-bin/fortune_or_date?date> The CGI program (fortune_or_date in this case) would then see which of the two possible arguments it received and execute either the fortune or date program accordingly. So you see that arguments do not have to be of the name=date variety characteristic of fill-out forms. You can write a CGI program to do most anything you please, and you can pass it most any arguments you please. In this chapter, we will primarily illustrate HTML fill-out forms. And we will assume that you understand basic HTML code already.[3]
[3] For the full story about HTML, see HTML: The Definitive Guide, Second Edition, O'Reilly & Associates.
Previous: 18.1 The CGI.pm Module Learning Perl on Win32 Systems Book Index Next: 18.3 Simplest CGI Program
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
sufficient step to making sure your program will run as a server script. A lot of other things can go wrong; see the section on "Troubleshooting CGI Programs" later in this chapter. After it runs properly from the command line, you need to get the program installed on the server machine. Acceptable locations are server- and machine-dependent, although the scripts or cgi-bin directory of your server installation is a good place to start looking. Consult your server documentation or options to be sure. After your program is installed in a CGI directory, you can execute it by giving its pathname to your browser as part of a URL. For example, if your program is called howdy.plx, the pathname would be: http://www.SOMEWHERE.org/cgi-bin/howdy.plx Servers typically define aliases for long pathnames. The server at www.SOMEWHERE.org might well translate cgi-bin/howdy.plx in this URL to something like c:\inetpub\scripts\howdy.plx.
Previous: 18.2 Your CGI Program in Context Learning Perl on Win32 Systems Book Index Next: 18.4 Passing Parameters via CGI
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
If given no arguments, param() returns a list of all the fields that were in the HTML form that this CGI script is responding to. (In the current example, this list contains the flavor field. In general, the list contains all the names in name=value strings received from the submitted form.) If given an argument naming a field, param() returns the value (or values) associated with that field. Therefore, param("flavor") returns "mint", because we passed in ?flavor=mint at the end of the URL. Even though we have only one item in our import list for use, we'll employ the qw() notation; this way it will be easier to expand the list later: # ice_cream.plx: program to answer ice cream # favorite flavor form (version 1) use CGI qw(param); print <<END_of_Start; Content-type: text/html <HTML> <HEAD> <TITLE>Hello World</TITLE> </HEAD> <BODY> <H1>Greetings, Terrans!</H1> END_of_Start my $favorite = param("flavor"); print "<P>Your favorite flavor is $favorite."; print <<All_Done; </BODY> </HTML> All_Done
Import all fill-out form generating methods, such as textfield(). :html2 Import all methods that generate HTML 2.0 standard elements. :html3 Import all methods that generate HTML 3.0 proposed elements (such as <table>, <super>, and <sub>). :netscape Import all methods that generate Netscape-specific HTML extensions. :shortcuts Import all HTML-generating shortcuts (that is, "html2" + "html3" + "netscape"). :standard Import "standard" features: "html2," "form," and "cgi." :all Import all the available methods. For the full list, see the CGI.pm module, where the variable %TAGS is defined. We'll just use :standard. (For more information about importing functions and variables from modules, see the Exporter module in Chapter 7 of Programming Perl.) Here's our program using all the shortcuts CGI.pm provides: # cgi-bin/ice_cream.plx: program to answer ice cream # favorite flavor form (version 2) use CGI qw(:standard); print header(), start_html("Hello World"), h1("Hello World"); my $favorite = param("flavor"); print p("Your favorite flavor is $favorite."); print end_html(); See how much easier that is? You don't have to worry about form decoding, headers, or HTML if you don't want to.
[7] Some browsers allow you to leave out the submit button when the form has only a single input text field. When the user types a return in this field, it is treated as a submit request. But you should use proper HTML here. <!-- ice_cream.html --> <HTML> <HEAD> <TITLE>Hello Ice Cream</TITLE> </HEAD> <BODY> <H1>Hello Ice Cream</H1> <FORM ACTION="http://www.SOMEWHERE.org/cgi-bin/ice_cream.plx"> What's your flavor? <INPUT NAME="favorite" VALUE="mint"> <P> <INPUT TYPE="submit"> </FORM> </BODY> </HTML> Remember that a CGI program can generate any HTML output that you want, which will then be passed to any browser that fetches the program's URL. A CGI program can, therefore, produce the HTML page with the form on it, just as a CGI program can respond to the user's form input. Moreover, the same program can perform both tasks, one after the other. All you need to do is divide the program into two parts, which do different things depending on whether or not the program was invoked with arguments. If no arguments were received, then the program sends the empty form to the browser; otherwise, the arguments contain a user's input to the previously sent form, and the program returns a response to the browser based on that input. Keeping everything in a single CGI file this way eases maintenance. The cost is a little more processing time when loading the original page. Here's how it works: # ice_cream.plx: program to answer *and generate* ice cream # favorite flavor form (version 3) use CGI qw(:standard); my $favorite = param("flavor"); print header, start_html("Hello Ice Cream"), h1("Hello Ice Cream"); if ($favorite) { print p("Your favorite flavor is $favorite."); } else { # hr() emits horizontal rule: <HR> print hr(), start_form(); print p("Please select a flavor: ", textfield("flavor","mint")); print end_form(), hr(); }
If, while using your browser, you click on a link that points to this program (and if the link does not specify ?whatever at the end of the URL), you'll see a screen like Figure 18.2. Figure 18.2: Screen shot of ice_cream.plx (without input)
Now, fill in the flavor field and press Return. Figure 18.3 will appear. Figure 18.3: Screen shot of ice_cream.plx with params (after input)
my $cost = sprintf("%.2f", $taxrate * (1.00 + $scoops * 0.25)); print p("Ok, $who, have $scoops scoops of $flavor for \$$cost."); } else { # first time through, so present clean form print hr(); # draw a horizontal rule before the form print start_form(); print p("What's your name? ", textfield("name")); # FOR EXPLANATION OF FOLLOWING TWO LINES, SEE NEXT SECTION print p("What flavor: ", popup_menu("flavor", ['mint','cherry','mocha'])); print p("How many scoops? ", popup_menu("scoops", [ 1..3 ])); print p(submit("order"), reset("clear")); print end_form(), hr(); } print end_html; Figure 18.4 shows the initial screen the textfield function generates. Figure 18.4: Screen shot of ice_cream.plx (final version)
As you'll recall, the param() function, when called without arguments, returns the names of all
form-input fields that were filled out. As a result, you can tell whether or not the URL was called from a filled-out form. If you have parameters, then the user filled in some of the fields of an existing form, so respond to them. Otherwise, generate a new form, expecting to have this very same program called a second time.
18.4.4 References
You may have noticed that the popup_menu() functions in the previous example both have a strange kind of argument. Just what are ['mint', 'cherry','mocha'] and [ 1..3 ] doing there? The brackets create something you haven't seen before: a reference to an anonymous array. The popup_menu() function expects an array reference for an argument. Another way to create an array reference is to use a backslash in front of a named array, as in \@choices. So this: @choices = ('mint','cherry','mocha'); print p("What flavor: ", popup_menu("flavor", \@choices)); works just as well as this: print p("What flavor: ", popup_menu("flavor", ['mint','cherry','mocha'])); References behave somewhat as pointers do in other languages, but with less danger of error. They're values that refer to other values (or variables). Perl references are very strongly typed (and uncastable), and they can never cause general protection faults. Even better, the memory storage pointed to by references is automatically reclaimed when it's no longer used. References play a central role in object-oriented programming. They're also used in traditional programming, forming the basis for data structures more complex than simple one-dimensional arrays and hashes. Perl supports references to both named and anonymous scalars, arrays, hashes, and functions. Just as you can create references to named arrays with \@array and to anonymous arrays with [ list ], you can also create references to named hashes using \%hash and to anonymous hashes using:[8] [8] Yes, braces now have quite a few meanings in Perl. The context in which you use them determines what they're doing. { key1, value1, key2, value2, ... } You can learn more about references in Chapter 4 of Programming Perl, or the perlref documentation.
-NAME => "flavors", -VALUES => [ qw(mint chocolate cherry vanilla peach) ], -LABELS => { mint => "Mighty Mint", chocolate => "Cherished Chocolate", cherry => "Cheery Cherry", vanilla => "Very Vanilla", peach => "Perfectly Peachy", }, -SIZE => 3, -MULTIPLE => 1, # 1 for true, 0 for false ); The parameter values have meanings as follows: -NAME The name of the widget. You can use the value of this later to retrieve user data from the form with param(). -VALUES A reference to an anonymous array. The array consists of the keys of the hash referenced by -LABELS. -LABELS A reference to an anonymous hash. The values of the hash provide the labels (list items) seen by the form user. When a particular label is selected by the user, the corresponding hash key is what gets returned to the CGI program. That is, if the user selects the item given as Perfectly Peachy, the CGI program will receive the argument peach. -SIZE A number determining how many list items will be visible to the user at one time. -MULTIPLE A true or false value (in Perl's sense of true and false) indicating whether the form user will be allowed to choose more than one list item. When you've set -MULTIPLE to true, you'll want to assign param()'s return list to an array: @choices = param("flavors"); Here's another way to create the same scrolling list, passing a reference to an existing hash instead of creating one on the fly: %flavors = ( mint => "Mighty Mint", chocolate => "Cherished Chocolate", cherry => "Cheery Cherry", vanilla => "Very Vanilla", peach => "Perfectly Peachy",
); print scrolling_list( -NAME => "flavors", -LABELS => \%flavors, -VALUES => [ keys %flavors ], -SIZE => 3, -MULTIPLE => 1, # 1 for true, 0 for false ); This time we send in values computed from the keys of the %flavors hash, which is itself passed in by reference using the backslash operator. Notice how the -VALUES parameter is still wrapped in square brackets? Passing in the result of keys as a list wouldn't work because the calling convention for the scrolling_list() function requires an array reference there, which the brackets happily provide. Think of the brackets as a convenient way to treat multiple values as a single value.
Previous: 18.3 Simplest CGI Program Learning Perl on Win32 Systems Book Index Next: 18.5 Creating a Guestbook Program
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
flock presents a simple but uniform locking mechanism even though its underlying implementation varies wildly between systems. It reliably blocks, not returning until it gets the lock. Note that file locks are purely advisory; they only work when all processes accessing a file honor the locks in the same way. If three processes honor them, but another doesn't, all bets are off.
method (which is what we were talking about a moment ago), except that instead of using an object to call the method, you use the name of the class as though it were itself an object. An object method is saying "call the function by this name that is related to this object"; a class method is saying "call the function by this name that is related to this class." Sometimes you'll see that same thing written this way: $query = new CGI; # same thing The second form is identical in behavior to the first. It's got less punctuation, so is sometimes preferred. But it's less convenient to use as part of a larger expression, so we'll use the first form exclusively in this book. From the standpoint of the designer of object modules, an object is a reference to a user-defined data structure, often an anonymous hash. Inside this structure is stored all manner of interesting information. But the well-behaved user of an object is expected to get at this information (to inspect or change it), not by treating the object as a reference and going straight for the data it points to, but by employing only the available object and class methods. Changing the object's data by other means amounts to hanky-panky that is bound to get you talked about. To learn what those methods are and how they work, just read the object module's documentation, usually included as embedded pods.
The program then downloads an HTML form to the browser, and for good measure also downloads any previous guest messages (up to a stated limit) for the user to review. The user then fills out the form, submits it, and the program reads what is submitted. This information is added to the list of previous messages (saved in a file), which is then output to the browser again, along with a fresh form. The user can continue reading the current set of messages and submitting new messages via the supplied forms as long as he wishes. Here's the program. You might want to scan it quickly before we step you through it. use strict; # enforce declarations and quoting use CGI qw(:standard); # import shortcuts sub bail { # function to handle errors gracefully my $error = "@_"; print h1("Unexpected Error"), p($error), end_html; die $error; } my( $CHATNAME, $MAXSAVE, $TITLE, $cur, @entries, $entry, $LOCK_EX, ); $LOCK_EX = 2; # hardcoded value for flock # # # # # # # name of guestbook file how many to keep page title and header new entry in the guestbook all cur entries one particular entry hardcoded value for flock
$TITLE = "Simple Guestbook"; $CHATNAME = "c:/temp/chatfile"; # wherever makes sense on your system $MAXSAVE = 10; print header, start_html($TITLE), h1($TITLE); $cur = CGI->new(); # current request if ($cur->param("message")) { # good, we got a message $cur->param("date", scalar localtime); # current time @entries = ($cur); # save message to array } # open the file for read-write (preserving old contents) open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!"); # get exclusive lock on the guestbook # ($LOCK_EX == exclusive lock) flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!");
# grab up to $MAXSAVE old entries, newest first while (!eof(CHANDLE) && @entries < $MAXSAVE) { # pass the filehandle by reference $entry = CGI->new(\*CHANDLE); push @entries, $entry; } seek(CHANDLE, 0, 0) || bail("cannot rewind $CHATNAME: $!"); foreach $entry (@entries) { $entry->save(\*CHANDLE); # pass the filehandle by reference } truncate(CHANDLE, tell(CHANDLE)) || bail("cannot truncate $CHATNAME: $!"); close(CHANDLE) || bail("cannot close $CHATNAME: $!"); print hr, start_form; # hr() emits html horizontal rule: <HR> print p("Name:", $cur->textfield( -NAME => "name")); print p("Message:", $cur->textfield( -NAME => "message", -OVERRIDE => 1, # clears previous message -SIZE => 50)); print p(submit("send"), reset("clear")); print end_form, hr; print h2("Prior Messages"); foreach $entry (@entries) { printf("%s [%s]: %s", $entry->param("date"), $entry->param("name"), $entry->param("message")); print br(); } print end_html; Figure 18.5 shows a sample screen dump after running the program a few times. Figure 18.5: Sample screen dump
Because every execution of the program results in the return of an HTML form to the particular browser that sought us out, the program begins by getting a start on the HTML code: print header, start_html($TITLE), h1($TITLE); The program then creates a new CGI object: $cur = CGI->new(); # current request if ($cur->param("message")) { # good, we got a message # set to the current time $cur->param("date", scalar localtime); @entries = ($cur); # save message to array } If we are being called via submission of a form, then the $cur object now contains information about the input text given to the form. The form we supply (as shown later) has two input fields: a name field for the name of the user, and a message field for the message. In addition, the code shown above puts a date stamp on the form data after it is received. Feeding the param() method two arguments is a way to set the parameter named in the first argument to the value given in the second argument. If we are not being called via submission of a form, but rather because the user has clicked on "Please
sign our guestbook," then the query object we create here will be empty. The if test will yield a false value, and no entry will be added to the @entries array. In either case, we proceed to check for any entries previously saved in our savefile. We will read those into the @entries array. (Recall that we have just now made the current form input, if any, the first member of this array.) But, first, we have to open the savefile: open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!"); This opens the file in nondestructive read-write mode. Alternatively, we could have used sysopen().[13] This way a single call opens an old file (if it exists) without clobbering it, or else creates a new one (note the use of the permission bits again): [13] For you C programmers, sysopen() is implemented in terms of open() rather than fopen(). # need to import two "constants" from Fcntl module for sysopen use Fcntl qw( O_RDWR O_CREAT ); sysopen(CHANDLE, $CHATNAME, O_RDWR|O_CREAT, 0666) || bail "can't open $CHATNAME: $!"; Then we lock the file, as described earlier, and proceed to read up to a total of $MAXSAVE entries into @entries: flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!"); while (!eof(CHANDLE) && @entries < $MAXSAVE) { # pass the filehandle by reference $entry = CGI->new(\*CHANDLE); push @entries, $entry; } eof is a Perl built-in function that tells whether we have hit the end-of-file. By repeatedly passing the new() method a reference to the savefile's filehandle,[14] we retrieve the old entries - one entry per call. Then, we update the file so that it now includes the new entry we (may) have just received: [14] Actually, this reference is a glob reference, not a filehandle reference, but it's close enough. seek(CHANDLE, 0, 0) || bail("cannot rewind $CHATNAME: $!"); foreach $entry (@entries) { $entry->save(\*CHANDLE); # pass the filehandle by reference } truncate(CHANDLE, tell(CHANDLE)) || bail("cannot truncate $CHATNAME: $!"); close(CHANDLE) || bail("cannot close $CHATNAME: $!"); seek, truncate, and tell are all built-in Perl functions whose descriptions you will find in any Perl reference work. Here seek repositions the file pointer to the beginning of the file, truncate truncates the indicated file to the specified length, and tell returns the current offset of the file pointer from the beginning of the file. The effect of these lines is to save only the most recent $MAXSAVE entries, beginning with the one just now received, in the savefile.
The save() method handles the actual writing of the entries. The method can be invoked here as $entry->save because $entry is a CGI object, created with CGI->new() as discussed above. The format of a savefile entry looks like this, where the entry is terminated by = standing alone on a line: NAME1=VALUE1 NAME2=VALUE2 NAME3=VALUE3 = Now it's time to return a fresh form to the browser and its user. (This form will be, of course, the first form he is seeing if he has just clicked on "Please sign our guestbook.") First, consider some preliminaries: print hr, start_form; # hr() emits html horizontal rule: <HR> As already mentioned, CGI.pm allows us to use either straight function calls or method calls via a CGI object. Here, for basic HTML code, we've reverted to the simple function calls. But for generation of form input fields, we continue to employ object methods: print p("Name:", $cur->textfield( -NAME => "name")); print p("Message:", $cur->textfield( -NAME => "message", -OVERRIDE => 1, # clears previous message -SIZE => 50)); print p(submit("send"), reset("clear")); print end_form, hr; The textfield() method returns a text input field for a form. The first of the two invocations here generates HTML code for a text input field with the HTML attribute NAME="name", while the second one creates a field with the attribute NAME="message". Widgets created by CGI.pm are by default sticky - they retain their values between calls. (This statement is true only during a single session with a form, beginning when the user clicks on "Please sign our guestbook.") Consequently, the NAME="name" field generated by the first textfield() above will have the value of the user's name if he already filled out and submitted the form at least once during this session. So the input field we are now creating will actually have these HTML attributes: NAME="name" VALUE="Sam Smith" The second invocation of textfield() is a different matter. We don't want the message field to contain the value of the old message. So the -OVERRIDE => 1 argument pair says, in effect, "throw out the previous value of this text field and restore the default value." The -SIZE => 50 argument pair of textfield() gives the size of the displayed input field in characters. Other optional argument pairs besides those shown include: -DEFAULT => 'initial value' and -MAXLENGTH => n, where n is the maximum number of input characters the field will accept. Finally, we output for the user's delectation the current set of saved messages, including, of course, any he has just submitted: print h2("Prior Messages");
foreach $entry (@entries) { printf("%s [%s]: %s", $entry->param("date"), $entry->param("name"), $entry->param("message")); print br(); } print end_html; As you will doubtless realize, the h2 function outputs a second-level HTML heading. For the rest, we simply iterate through the current list of saved entries (the same list we earlier wrote to the savefile), printing out date, name, and message from each one. Users can sit with the guestbook form, continually typing messages and pressing the submit button. This method simulates an electronic bulletin-board system, letting users see each other's new messages each time they send off their own. When they do this, they call the same CGI program repeatedly, which means that the previous widget values are automatically retained between invocations. This result is particularly convenient when creating multistage forms, such as those used in so-called "shopping cart" applications.
Previous: 18.4 Passing Parameters via CGI Learning Perl on Win32 Systems Book Index Next: 18.6 Troubleshooting CGI Programs
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
If, when sending HTML to a browser, you forget the blank line between the HTTP header (that is, the Content-Type line) and the body, your program won't work. Remember to output a proper Content-Type line (and possibly other HTTP headers) plus a totally blank line before you do anything else. The server needs to be able to read and execute the script, so you need to make sure that whatever user your script runs as (e.g., IUSR_MYSERVER under IIS) has read and execute rights to the script. The directory where the script resides must have read and execute rights for the script user. The script must be installed in the proper directory for your server configuration. For example, on some systems, the directory may be c:\inetpub\scripts.[16] [16] This directory is the default for IIS, Microsoft's Internet Information Server.
q q
You need to have your script's filename end in a particular suffix, like .cgi or .plx, so that your web server knows that it needs to invoke the Perl interpreter on your script. Make sure that your script directory is not writable by FTP clients. We suggest using a suffix of .plx, and associating .plx with your Perl interpreter. Your server configuration requires CGI execution specially enabled for the directory you put your CGI script in. Make sure both GET and POST are allowed. Normally, the web server doesn't execute your script using your account. Make sure the files and
directories accessed by the script are open to whatever user the script will run as; this might be the IUSR_INTERNET or anoynmous account, or whatever account you use on your system. You may need to pre-create such files and directories and give them appropriate permissions. Always be alert to the risks when you grant such access to files.
q
Always run your script under Perl's -w flag to get warnings. These warnings go to the web server error log, which contains any errors and warnings generated by your script. Learn the path to that logfile from your webmaster and check it for problems. See also the standard CGI::Carp module for how to handle errors better. Make sure that the versions and paths to Perl and any libraries you use (like CGI.pm) are what you're expecting them to be over on the machine the web server is running on. Enable autoflush on the STDOUT filehandle at the top of your script by setting the $| variable to a true value, like one. If you've used the FileHandle module or any of the IO modules (like IO::File, IO::Socket, and so on), then you can use the more mnemonically named autoflush() method on the filehandle instead: use FileHandle; STDOUT->autoflush(1); Check the return value of every system call your program makes, and take appropriate action if the call fails.
Learning Perl on Win32 Systems Book Index Next: 18.7 Perl and the Web: Beyond CGI Programming
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
the Perl interpreter to handle the request from the new thread. This can provide significant performance benefits in situations where the server receives a high number of hits. The current version of PerlIS (Build 306) has some instability when launching external processes and when creating socket connections. If you can't get something to work that you need, we suggest running your script as a CGI program using the standalone interpreter. Look for improved stability in future releases of PerlIS. PerlScript can not only be used to generate Active Server Pages, but also as a client-side scripting language in the same manner as VBScript or JavaScript. For more information on PerlScript, see www.activestate.com. For more information on Active Server Pages, see the Microsoft ASP roadmap at www.microsoft.com/iis/usingiis/resources/ASPdocs/roadmap.asp, which provides a detailed overview of Active Server Pages and the automation objects that a server provides to PerlScript.
Previous: 18.6 Troubleshooting CGI Programs Learning Perl on Win32 Systems Book Index Next: 18.8 Further Reading
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
CGI.pm documentation The LWP library from CPAN (runs under Windows NT with a few modifications - see the documentation for more information) CGI Programming on the World Wide Web (Shishir Gundavaram, O'Reilly & Associates, 1996) Web Client Programming with Perl (Clinton Wong, O'Reilly & Associates, 1997) HTML: The Definitive Guide, Second Edition (Chuck Musciano & Bill Kennedy, O'Reilly & Associates, 1997) How to Set Up and Maintain a Web Site, Second Edition (Lincoln D. Stein, Addison-Wesley, 1996) Nick Kew's CGI FAQ Perl documentation: perltoot, perlref, perlmod, perlobj
Learning Perl on Win32 Systems Book Index Next: 18.9 Exercises
q q q
q q
18.9 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
18.9 Exercises
See Appendix A, Exercise Answers for answers. 1. Write a form that provides two input fields that are added together when the user submits it. 2. Write a CGI script that detects the browser type making the request, and then prints something appropriate (hint: look at the HTTP_USER_AGENT environment variable).
Previous: 18.8 Further Reading Learning Perl on Win32 Systems Book Index Next: 19. OLE Automation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Chapter 19
value, you can also use a short form: $val = $obj->foo; $obj->foo = $val;
Now, we know that we can control our favorite automation servers from Perl. But how do we know what methods, properties, and objects a server exposes? The answer, unfortunately, it that these things are completely server dependent. No standards for object names, methods, or properties exist. The best solution is to turn to your server's documentation for answers. If the server doesn't provide documentation, your situation is still not completely hopeless. If the automation server provides typelib information (an OLE mechanism to describe the interfaces that an OLE server provides), you can use an OLE object viewer (such as Microsoft's OLE2VW32.EXE) that can read OLE typelib information and try to figure out what methods and properties the object exposes on your own. Automation servers come in a couple of different flavors. There are local servers that live in an application (.exe file) and run as their own processes. There are in-proc servers that live in DLLs (dynamic-link libraries) and run in the process of the automation controller. There are also remote servers that may run on a different machine using Distributed COM (DCOM). Perl for Win32 cannot currently use OCX controls, which require additional OLE support.
Previous: 18.9 Exercises Learning Perl on Win32 Systems Book Index Next: 19.2 Creating Automation Objects
18.9 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
will contain the automation object if the function returns successfully. Throughout this chapter, we'll be using the ActiveState syntax for our automation examples.
Previous: 19.1 Introduction to OLE Automation Learning Perl on Win32 Systems Book Index Next: 19.3 Using Automation Objects
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Outbox that returns an automation object (the Outbox object). We're then calling a method of the Outbox object called Messages that returns another automation object (the Message object). We're then calling a method of the Message object named Add that returns yet another automation object, which we're assiging to our $Message variable. Perl lets you merrily create as many nested automation objects as you need. Now that we have a Message object, we can start doing things with the message. First, we need to add a recipient. This involves another nested automation-object call: $Recipient = $Message->Recipients->Add(); Here we're calling the Recipients method of the message object that returns a recipients object. We then call the Add method of the recipients object to get a Recipient object that we can use. Let's set some properties of the recipient object: $Recipient->{Name} = "Erik Olson"; # to address $Recipient->{Type} = 1; # ugly constant, means this is a To address We've set the Name property of the Recipient object by setting the property using the object's hash. As for that assignment to the Type property, we've set it to 1, which is the Active Messaging value for a TO recipient (as opposed to a CC or BCC recipient). Table 19.1 displays the values for the recipient types.
Table 19.1: Recipient Type Values Recipient Type MAPI_ORIG (recipient is message originator) MAPI_TO (recipient is a primary recipient) MAPI_CC (recipient is a copy recipient) Value 0 1 2
MAPI_BCC (recipient is a blind copy recipient) 3 After setting the recipient information, we need to resolve it to a name in the Active Messaging address book. We do this by calling the Resolve member of the Recipient object: $Recipient->Resolve(); Now that we know where our message is going, let's add some data to it. We need at least a subject and a body, both of which are properties of the Message object. $Message->{Subject} = "A Message From Perl"; $Message->{text} = "Perl does automation!"; All that remains is to save the message, send it, and terminate our session: $Message->Update(); $Message->Send(1, 0, 0); $Message->Logoff(); We call the Update method of the message object to save it, then the Send method to actually send the message. The parameters to Send are shown in Table 19.2.
Table 19.2: Send Parameters Parameter saveCopy showDialog Meaning Save a copy of the message in the Sent-Items folder (one or zero) Display a send-message dialog where the user can change the message contents or recipients (1 or 0)
parentWindow Parent-window handle for the dialog, if showDialog is true; in Perl, you'll normally be passing this as 0 Let's put everything together: use OLE; $LogonName = "Erik Olson"; # send message to me $LogonPasswd = undef; # use stored passwd $ActiveSession = CreateObject OLE "MAPI.Session" || die "CreateObject: $!"; # create session die "Logon: $!" if $ActiveSession->Logon($LogonName, $LogonPasswd); # logon (returns 0 on success) $Message = $ActiveSession->Outbox->Messages->Add(); $Recipient = $Message->Recipients->Add(); $Recipient->{Name} = "Erik Olson"; # to address # ugly constant, means this is a To address $Recipient->{Type} = 1; $Recipient->Resolve(); # resolve name - hope it's there $Message->{Subject} = "A Message From Perl"; $Message->{text} = "Perl does automation!"; $Message->Update(); # save it $Message->Send(1, 0, 0); # send it - don't show UI $ActiveSession->Logoff(); # end session
the rows in the Employees table. Regardless of which data source you choose to use ADO with, you'll find the procedure to be similiar. use OLE; $conn = CreateObject OLE "ADODB.Connection" || die "CreateObject: $!"; # create ADO auto object $conn->Open('OLE_DB_NWind_Jet'); # connect to data source $sql = "SELECT * FROM Employees ORDER BY LastName, FirstName"; $rs = $conn->Execute($sql); # grab all records in table while(!$rs->EOF()) { $lastname = $rs->Fields('LastName')->Value; $firstname = $rs->Fields('FirstName')->Value; $empid = $rs->Fields('EmployeeId')->Value; write; # print them out $rs->MoveNext(); } $rs->Close(); # shut down the recordset $conn->Close(); # close the data source # some formats for a quick printout format STDOUT = @<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< $empid, $firstname, $lastname . format STDOUT_TOP = Page @<< $% ID First Last ===== ==================== ========================= . Our first task is to create the automation object using the now familiar CreateObject function. We then use the ADO Connection object to execute a SQL statement. The Execute function returns a Recordset object, which we then use to iterate through all the rows, printing out the data. Here's another quick program that inserts an employee into the Employees table: use OLE; $firstname = "Homer"; # hardcode some values to insert $lastname = "Simpson"; $empid = "3001"; $conn = CreateObject OLE "ADODB.Connection" || die "CreateObject: $!"; # create the ADO object $conn->Open('OLE_DB_NWind_Jet'); # connect to the data source # build a simple SQL INSERT $sql = "INSERT into Employees (LastName, FirstName, EmployeeID)"; $sql .= "VALUES ('$lastname', '$firstname', '$empid')"; $conn->Execute($sql); # run it
$conn->Close();
Previous: 19.2 Creating Automation Objects Learning Perl on Win32 Systems Book Index Next: 19.4 Variants
19.4 Variants
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
19.4 Variants
In order for automation controllers and servers to cooperate, they have to have some way to agree on the type of data that they're passing. Automation accomplishes this through a data type called a VARIANT. The VARIANT data type is built on a C-language union. It contains a type field that identifies that type of data in the union (things such as strings, numbers, automation objects, etc.) and a field that contains the data. Usually, Perl handles data-type conversion for you. If you need more control, though, you can create a Variant object and specify the type yourself. Perl provides access to the types listed in Table 19.3.
Table 19.3: Variant Types Variant Type Description VT_UI1 VT_I2 VT_I4 VT_R4 VT_R8 VT_DATE VT_BSTR VT_CY VT_BOOL Unsigned character (1 byte) Signed integer (2 bytes) Signed integer (4 bytes) Floating point (4 bytes) Floating point (8 bytes) OLE Date (floating-point value measuring days since midnight, Dec. 30, 1899) OLE String OLE Currency OLE Boolean
By default, Perl converts integer data to the VT_I4 type, string data to the VT_BSTR type, and floating-point data to the VT_R8 type. Usually, these conversions are what you'd expect, but let's look at how you might specify your own type: $vt = new OLE::Variant(OLE::VT_DATE, "May 31, 1997" ); $Message->{TimeSent} = $vt;
This example first creates a Variant object, setting the type to VT_DATE and the date to "May 31, 1997." It then assigns the date to the Message object TimeSent property (something you might do if you were posting a message to a folder, for example).
Previous: 19.3 Using Automation Objects Learning Perl on Win32 Systems Book Index Next: 19.5 Tips and Techniques
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
19.4 Variants
19.6 Exercises
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
19.6 Exercises
1. Write a program that will invoke your favorite automation-enabled web browser and take it to the O'Reilly & Associates Perl home page (http://www.ora.com/publishing/perl ). 2. Write a program that reads a list of numbers and uses automation to put them in sequential rows in your favorite spreadsheet.
Previous: 19.5 Tips and Techniques Learning Perl on Win32 Systems Book Index Next: A. Exercise Answers
A. Exercise Answers
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Appendix A
A. Exercise Answers
Contents: Chapter 2, Scalar Data Chapter 3, Arrays and List Data Chapter 4, Control Structures Chapter 5, Hashes Chapter 6, Basic I/O Chapter 7, Regular Expressions Chapter 8, Functions Chapter 9, Miscellaneous Control Structures Chapter 10, Filehandles and File Tests Chapter 11, Formats Chapter 12, Directory Access Chapter 13, File and Directory Manipulation Chapter 14, Process Management Chapter 15, Other Data Transformation Chapter 16, System Information Chapter 17, Database Manipulation Chapter 18, CGI Programming Chapter 19, OLE Automation This appendix gives the answers for the exercises found at the end of each chapter.
circumference using this value of $pi in an expression. Finally, we print the result using a string containing a reference to the result. 2. Here's one way to do it: print "What is the radius: "; chomp($radius = <STDIN>); $pi = 3.141592654; $result = 2 * $pi * $radius; print "radius $radius is circumference $result\n"; This is similar to the previous exercise, but in this case, we've asked the person running the program for a value, using a print statement for a prompt, and then the <STDIN> operator to read a line from the terminal. If we had left off the chomp, we'd get a newline in the middle of the displayed string at the end. You must get that newline off the string as soon as you can. 3. Here's one way to do it: print "First number: "; chomp($a = <STDIN>); print "Second number: "; chomp($b = <STDIN>); $c = $a * $b; print "Answer is $c\n"; The first line does three things: prompts you with a message, reads a line from standard input, and then gets rid of the inevitable newline at the end of the string. Note that because we are using the value of $a strictly as a number, we can omit the chomp here, because 45\n is 45 when used numerically. However, such careless programming would likely come back to haunt us later on (for example, if we were to include $a in a message). The second line does the same thing for the second number and places it into the scalar variable $b. The third line multiplies the two numbers together and prints the result. Note the newline at the end of the string here, contrasted with its absence in the first two lines. The first two messages are prompts, for which user input was desired on the same line. 4. Here's one way to do it: print "String: "; $a = <STDIN>; print "Number of times: "; chomp($b = <STDIN>); $c = $a x $b; print "The result is:\n$c"; As with the previous exercise, the first two lines ask for, and accept, values for the two variables. Unlike the previous exercise, we don't chomp the newline from the end of the string, because we need it! The third line takes the two entered values and performs a string repetition on them, and then displays the answer. Note that the interpolation of $c is not followed by a newline, because we believe that $c will always end in a newline anyway.
Previous: 19.6 Exercises Learning Perl on Win32 Systems Next: A.2 Chapter 3, Arrays and List Data
19.6 Exercises
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
The first line initializes the random number generator. The second line reads a bunch of strings. The third line selects a random element from that bunch of strings and prints it.
Previous: A.1 Chapter 2, Scalar Data Learning Perl on Win32 Systems Book Index Next: A.3 Chapter 4, Control Structures
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
chomp($n = <STDIN>); } print "the sum is $sum\n"; The first line prompts for the first number. The second line reads the number from the terminal. The while loop continues to execute as long as the number is not 999. The += operator accumulates the numbers into the $sum variable. Note that the initial value of $sum is undef, which makes a nice value for an accumulator, because the first value added in will be effectively added to 0 (remember that undef used as a number is 0). Within the loop, we must prompt for and receive another number, so that the test at the top of the loop is against a newly entered number. When the loop is exited, the program prints the accumulated results. Note that if you enter 999 right away, the value of $sum is not 0, but an empty string - the value of undef when used as a string. If you want to ensure that the program prints 0 in this case, you should initialize the value of $sum at the beginning of the program with $sum = 0. 4. Here's one way to do it: print "Enter some strings, end with ^Z:\n"; @strings = <STDIN>; while (@strings) { print pop @strings; } First, this program asks for the strings. These strings are saved in the array variable @strings, one per element. The control expression of the while loop is @strings. The control expression is looking for a single value (true or false), and is therefore computing the expression in a scalar context. The name of an array (such as @strings) when used in a scalar context is the number of elements currently in the array. As long as the array is not empty, this number is non-zero, and therefore true. This is a very common Perl idiom for "do this while the array is non-empty." The body of the loop prints a value, obtained by pop'ing off the rightmost element of the array. Thus, each time through the loop, the array is one element shorter, because that element has been printed. You may have considered using subscripts for this problem. As we say, there's more than one way to do it. However, you'll rarely see subscripts in a true Perl Hacker's programs because a better way almost always exists. 5. Here's a way to do it without a list: for ($number = 0; $number <= 32; $number++) { $square = $number * $number; printf "%5g %8g\n", $number, $square; }
And here's how to do it with a list: foreach $number (0..32) { $square = $number * $number; printf "%5g %8g\n", $number, $square; } These solutions both involve loops, using the for and foreach statements. The body of the loops are identical, because for both solutions, the value of $number proceeds from 0 to 32 on each iteration. The first solution uses a traditional C-like for statement. The three expressions respectively: set $number to 0, test to see if $number is less than 32, and increment $number on each iteration. The second solution uses a foreach statement. A list of 33 elements (0 to 32) is created, using the list contructor. The variable $number is then set to each element in turn.
Previous: A.2 Chapter 3, Arrays and List Data Learning Perl on Win32 Systems Book Index Next: A.4 Chapter 5, Hashes
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
both sides of the assignment when a simple autoincrement will do. After the words have been counted, the last few lines step through the hash by looking at each of its keys one at a time. The key and the corresponding value are printed after having been interpolated into the string. The extra-challenge answer looks like this answer, with the sort operator inserted just before the word keys on the third-to-last line. Without the sorting, the resulting output is seemingly random and unpredictable. However, after being sorted, the output is predictable and consistent. (Personally, I rarely use the keys operator without also adding a sort immediately in front of it this method ensures that reruns over the same or similar data generate comparable results.)
Previous: A.3 Chapter 4, Control Structures Learning Perl on Win32 Systems Book Index Next: A.5 Chapter 6, Basic I/O
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
The foreach loop steps through this array, giving $_ the value of each line. The printf operator gets two arguments: the first argument defines the format - %20s\n means a 20-character right-justified column, followed by a newline. 4. Here's one way to do it: print "Field width: "; chomp($width = <STDIN>); print "List of strings:\n"; chomp(@strings = <STDIN>); foreach (@strings) { printf "%${width}s\n", $_; } To the previous exercise's answer, we've added a prompt and response for the field width. The other change is that the printf format string now contains a variable reference. The value of $width is included into the string before printf considers the format. Note that we cannot write this string as: printf "%$widths\n", $_; # WRONG because then Perl would be looking for a variable named $widths, not a variable named $width to which we attach an s. Another way to write this is: printf "%$width"."s\n", $_; # RIGHT because the termination of the string also terminates the variable name, protecting the following character from being sucked up into the name.
Previous: A.4 Chapter 5, Hashes Learning Perl on Win32 Systems Book Index Next: A.6 Chapter 7, Regular Expressions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
expression, that looks for the five vowels in sequence, separated by any number of characters. c. A third way to do this is: while (<STDIN>) { if (/^[eiou]*a[^iou]*e[^aou]*i[^aeu]*o[^aei]*u[^aeio]*$/i) { print; } } This solution is ugly, but it works. To construct this solution, just think "What can go between the beginning of the line, and the first a?" Then, think "What can go between the first a and the first e?" Eventually, everything works out, with a little assistance from you.
Previous: A.5 Chapter 6, Basic I/O Learning Perl on Win32 Systems Book Index Next: A.7 Chapter 8, Functions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
evaluated, returning $num as the return value. The driver routine takes successive lines, chomping off their newlines, and hands them one at a time to the &card routine, printing the result. 2. Here's one way to do it: sub card { ...; } # from previous problem print "Enter first number: "; chomp($first = <STDIN>); print "Enter second number: "; chomp($second = <STDIN>); $message = &card($first) . " plus " . &card($second) . " equals " . &card($first+$second) . ".\n"; print "\u$message"; The first two print statements prompt for two numbers, with the immediately following statements reading the values into $first and $second. A string called $message is then built up by calling &card three times, once for each value, and once for the sum. After the message is constructed, its first character is uppercased by the case-shifting backslash operator \u. The message is then printed. 3. Here's one way to do it: sub card { my %card_map; @card_map{0..9} = qw( zero one two three four five six seven eight nine ); my($num) = @_; my($negative); if ($num < 0) { $negative = "negative "; $num = - $num; } if ($card_map{$num}) { $negative . $card_map{$num}; # return value } else { $negative . $num; # return value } } Here, we've given the %card_map array a name for 0. The first if statement inverts the sign of $num, and sets $negative to the word negative, if the
number is found to be less than 0. After this if statement, the value of $num is always non-negative, but we will have an appropriate prefix string in $negative. The second if statement determines if the (now positive) $num is within the hash. If so, the resulting hash value is appended to the prefix within $negative, and returned. If not, the value within $negative is attached to the original number. That last if statement can be replaced with the expression: $negative . ($card_map{$num} || $num);
Previous: A.6 Chapter 7, Regular Expressions Learning Perl on Win32 Systems Book Index Next: A.8 Chapter 9, Miscellaneous Control Structures
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
again.
Previous: A.7 Chapter 8, Functions Learning Perl on Win32 Systems Book Index Next: A.9 Chapter 10, Filehandles and File Tests
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
This program is based on the file-copying program presented earlier in the chapter. New features here include the prompts for the strings, the substitute command in the middle of the while loop, and the test for overwriting a file. Note that backreferences in the regular expression do work, but references to memory in the replacement string do not. 3. Here's one way to do it: while (<>) { chomp; # eliminate the newline print "$_ is readable\n" if -r; print "$_ is writable\n" if -w; print "$_ is executable\n" if -x; print "$_ does not exist\n" unless -e; } This while loop reads a filename each time through. After discarding the newline, the series of statements tests the file for the various permissions. 4. Here's one way to do it: while (<>) { chomp; $age = -M; if ($oldest_age < $age) { $oldest_name = $_; $oldest_age = $age; } } print "The oldest file is $oldest_name ", "and is $oldest_age days old.\n"; First, we loop on each filename being read in. The newline is discarded, and then the age (in days) gets computed with the -M operator. If the age for this file exceeds the oldest file we've seen so far, we remember the filename and its corresponding age. Initially, $oldest_age will be zero, so we're counting on there being at least one file that is more than zero days old. The final print statement generates the report when we're done.
Previous: A.8 Chapter 9, Miscellaneous Control Structures Learning Perl on Win32 Systems Book Index Next: A.10 Chapter 11, Formats
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
format STDOUT_TOP = Page @<<< $% User ============== . Company ======================= Real Name =================
Well, here again, to get stuff at the top of the page, we've added a top-of-page format. This format also contains a reference to $%, which gives us a page number automatically.
Previous: A.9 Chapter 10, Filehandles and File Tests Learning Perl on Win32 Systems Book Index Next: A.11 Chapter 12, Directory Access
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
chdir($newdir) || die "Cannot chdir to $newdir: $!"; foreach (sort <* .*>) { print "$_\n"; } Yes, this solution is basically the other program from the previous exercise, but I've added a sort operator in front of the glob, and I also added .* to the glob to pick up the files that begin with dot. We need the sort because a file named !fred belongs before the dot files, and barney belongs after them. In addition, an easy glob pattern that can get them all in the proper sequence does not exist.
Previous: A.10 Chapter 11, Formats Learning Perl on Win32 Systems Book Index Next: A.12 Chapter 13, File and Directory Manipulation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
We check to make sure both arguments are really directories, then we invoke xcopy to do the dirty work. We could have also used: system("xcopy /s /e $src $trg"); 2. Here's one way to do it: @hosts = `net view`; foreach (@hosts) { next unless m#\\\\#; chop; s/^(\S+).*/$1/; push @sorted, $_; } print join("\n", sort @sorted); We run the command net view and capture the output as a list of lines. We then go through each line looking for hostnames (they start with \\), chop off newlines and comments, and add the matches to another list. We then sort the second list and print it.
Previous: A.12 Chapter 13, File and Directory Manipulation Learning Perl on Win32 Systems Book Index Next: A.14 Chapter 15, Other Data Transformation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
For each line read by the diamond operator, we use two tr operators, each on a different portion of the string. The first tr operator uppercases the first character of the line, and the second tr operator lowercases the remainder. The result is printed. Another way to do this, using only double-quoted string operators, is: while (<>) { print "\u\L$_"; } Give yourself an extra five points if you thought of that method instead.
Previous: A.13 Chapter 14, Process Management Learning Perl on Win32 Systems Book Index Next: A.15 Chapter 16, System Information
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
# break it into components # strip initial path separator, if there is one $path =~ s#^\\##; my (@klist) = split(/\\/, $path); my $key; my $regkey = $subtree; foreach $key (@klist) { $regkey->Create($key, $regkey) || die "Can't create key $key: $!"; } return $regkey; } We first strip the leading backslash out of the path, then break it into a series of keys. We then iterate over each key, creating the key (remember, create opens it if it already exists) and return the deepest key. We're assuming that we have passed in an open key as the first argument. 4. Here's one way to do it: sub print_dword_key { my ($dw) = @_; printf ("0x%x", unpack("l", $dw)); } This subroutine takes a scalar value that's assumed to be a four-byte integer value and unpacks it using the long format l (which unpacks a four-byte integer). The subroutine then uses printf and its hexidecimal specifier (%x) prefixed with 0x to print out the value.
Previous: A.14 Chapter 15, Other Data Transformation Learning Perl on Win32 Systems Book Index Next: A.16 Chapter 17, Database Manipulation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
} elsif (/lynx/i) { lynx($_); } else { default($_); } print end_html(); sub msie{ print p("Internet Explorer: @_. Good Choice\n"); } sub netscape { print p("Netscape: @_. Good Choice\n"); } sub lynx { print p("Lynx: @_. Shudder..."); } sub default { print p("What the heck is a @_?"); } The key here is checking the environment for the HTTP_USER_AGENT variable (line 5). Although this step isn't implemented by every server, many of them do set the variable. This method is a good way to generate content geared at the features of a particular browser. Note that we're just doing some basic string matching (case insensitive) to see what they're using (nothing too fancy). Experienced Perl programmers would probably prefer to write the string-matching section more along these lines: BROWSER:{ /msie/i and do { msie($_), last BROWSER; }; /mozilla/i and do { netscape($_), last BROWSER; }; /lynx/i and do { lynx($_), last BROWSER; }; default($_); } However we haven't talked about this construct in this book. If you're interested, see Chapter 2 of Programming Perl for several other ways to emulate a switch construct.
Previous: A.16 Chapter 17, Database Manipulation Learning Perl on Win32 Systems Book Index Next: A.18 Chapter 19, OLE Automation
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
$xl->Workbooks->Add(); # start at the top left $col = "A"; $row = 1; foreach $num (@numbers) { chomp($num); $cell = sprintf("%s%d", $col, $row++); # add it to Excel $xl->Range($cell)->{Value} = $num; } The first task is to grab our list of numbers (you'll need to enter CTRL-Z to terminate the input). After that, we create an Excel application object, make it visible by setting the {Visible} property, and then add a new workbook. Then, we iterate over our array of numbers and add them to Excel, incrementing the row counter as we go. Note that we could have saved this workbook using the Save method, and then terminated Excel using the Quit method, but we chose not to, so that we could see what was going on more easily.
Previous: A.17 Chapter 18, CGI Programming Learning Perl on Win32 Systems Book Index Next: B. Libraries and Modules
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Appendix B
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Manipulates @INC at compile time Shell Runs shell commands transparently within Perl strict Restricts unsafe constructs Symbol Generates anonymous globs; qualifies variable names subs Predeclares subroutine names vars Predeclares global variable names
Runs many tests on a collection of files File::Copy Copies files or filehandles File::Find Traverses a file tree File::Path Creates or removes a series of directories FileCache Keeps more files open than the system permits FileHandle Supplies object methods for filehandles SelectSaver Saves and restores selected filehandles
NDBM_File Provides tied access to NDBM files ODBM_File Provides tied access to ODBM files SDBM_File Provides tied access to SDBM files
B.2.7 Mathematics
Integer Does integer arithmetic instead of double precision Math::BigFloat Provides arbitrary-length, floating-point math package Math::BigInt Provides arbitrary-length integer math package Math::Complex Provides complex numbers package
Net::hostent Provides object interface to gethost* functions Net::netent Provides object interface to getnet* functions Net::protoent Provides object interface to getproto* functions Net::servent Provides object interface to getserv* functions Time::gmtime Provides object interface to gmtime function Time::localtime Provides object interface to localtime function Time::tm Provides internal object for Time::{gm,local}time User::grent Provides object interface to getgr* functions User::pwent Provides object interface to getpw* functions
Provides pragma for use with Opcode module POSIX Interfaces to IEEE Std 1003.1 Safe Creates safe namespaces for evaluating Perl code Test::Harness Runs Perl standard test scripts with statistics vmsish Enables VMS-specific features
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Module listing format Perl core modules, Perl language extensions, and documentation tools Development support Operating system interfaces Networking, device control (modems), and interprocess communication Data types and data type utilities Database interfaces User interfaces Interfaces to or emulations of other programming languages Filenames, filesystems, and file locking (see also filehandles) String processing, language text processing, parsing, and searching Option, argument, parameter, and configuration-file processing Internationalization and locale Authentication, security, and encryption World Wide Web, HTML, HTTP, CGI, and MIME Server and daemon utilities
q q q q q q q
Archiving, compression, and conversion Images, pixmap and bitmap manipulation, drawing and graphing Mail and Usenet news Control-flow utilities (callbacks and exceptions) Filehandle, directory handle, and input/output stream utilities Microsoft Windows modules Miscellaneous modules
Learning Perl on Win32 Systems Book Index Next: B.4 Win32 Extensions
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Provides an interface to the system error codes and messages The following Win32 extensions are not included in (but are readily available for) the ActiveState distribution, and are included with the libwin32 distribution. Win32::Internet Provides an interface to HTTP and FTP Win32::ODBC Provides an interface to ODBC data sources Win32::Shortcut Lets you create Explorer (shell) shortcuts Win32::Sound Plays .wav files or uses system sounds Win32::AdminMisc Provides an extension of Win32::NetAdmin that adds user impersonation, password manipulation, and DNS administration Win32::Clipboard Accesses the Windows NT clipboard Win32::Console Interfaces to console screen drawing; lets you do colors, boxes, etc. Win32::Pipe Provides access to named pipes on Windows NT In addition to these extensions, a Win32 extension is included with the ActiveState distribution, and is available as part of libwin32. The Win32 extension provides the following list functions (we've given a brief code snippet to illustrate how you might code each one): Win32::GetLastError Returns the last error value generated by a call to a Win32 API function: use Win32; $err = Win32::GetLastError(); Win32::BuildNumber Returns the build number of Perl for Win32: use Win32: $build = Win32::BuildNumber(); # $build has 306 (or whatever it is) Win32::LoginName Returns the username of the owner of the current perl process: use Win32; $user = Win32::LoginName(); # $user has eriko (account name of current user) Win32::NodeName Returns the Microsoft Network node name of the current machine: use Win32; $node = Win32::NodeName(); # $node has machine name Win32::DomainName
Returns the name of the Microsoft Network domain that the owner of the current perl process is logged into: use Win32; $domain = Win32::Domain(); # $domain has network domain name (not TCP/IP domain name) Win32::FsType Returns a string naming the filesystem type of the currently active drive: use Win32; $fs = Win32::FsType(); # $fs contains fs type, like NTFS or FAT Win32::GetCwd Returns the current active drive and directory; this function does not return a UNC path: use Win32; $cwd = Win32::GetCwd(); # $cwd has current working directory Win32::SetCwd NEW_DIRECTORY Sets the current active drive and directory; this function does not work with UNC paths: use Win32; Win32::SetCwd("c:/temp") || die "SetCwd: $!"; Win32::GetOSVersion Returns an array ($string, $major, $minor, $build, and $id). $string is a descriptive string, $major is the major version of the operating system, $minor is the minor version of the operating system, $build is the build number of the OS, and $id is a digit that denotes the operating system variety (zero for Win32s, one for Windows 95, and two for Windows NT): use Win32; ($string, $major, $minor, $build, $id) = Win32::GetOSVersion(); @os = qw(Win32s, Win95, WinNT); print "$os[$id] $major\.$minor $string (Build $build)\n"; The output on a Windows NT 4.0 system is: WinNT 4.0 Service Pack 3 (Build 1381) Win32::FormatMessage ERROR_CODE Converts the supplied Win32 error bitmap (returned by GetLastError) to a descriptive string: use Win32; use Win32::WinError; # for error constants $msg = Win32::FormatMessage(ERROR_INTERNAL_ERROR); # $msg contains the string: There is not enough space on disk Win32::Spawn COMMAND, ARGS, PID Spawns a new process using the supplied COMMAND, passing in arguments in the string ARGS; the pid of the new process is stored in PID: use Win32; Win32::Spawn('c:/nt/system32/notepad.exe', undef, $pid); # $pid has new pid of notepad Win32::LookupAccountName SYSTEM, ACCOUNT, DOMAIN, SID, SIDTYPE Looks up ACCOUNT on SYSTEM and returns the domain name, SID, and SID type Win32::LookupAccountSID SYSTEM, SID, ACCOUNT, DOMAIN, SIDTYPE Looks up SID (Security ID) on SYSTEM and returns the account name, domain name, and SID type: use Win32; Win32::LookupAccountSID(undef, $some_sid, $acct, $domain, $sidtype);
Win32::InitiateSystemShutdown MACHINE, MESSAGE, TIMEOUT, FORCECLOSE, REBOOT Shuts down the specified MACHINE (undef means local machine), notifying users with the supplied MESSAGE, within the specified TIMEOUT (in seconds) interval. Forces closing of all documents without prompting the user if FORCECLOSE is true, and reboots the machine if REBOOT is true (be careful experimenting with this one): use Win32; Win32::InitiateSystemShutdown(undef, "Bye", 15, undef, 1); # try to shut down local machine Win32::AbortSystemShutdown MACHINE Aborts a shutdown on the specified MACHINE: use Win32; Win32::AbortSystemShutdown(undef); # stop a shutdown on local machine Win32::GetTickCount Returns the Win32 tick count, which is the number of milliseconds that have elasped since the system started: use Win32; $tick = Win32::GetTickCount(); # tick has number of milliseconds since system start Win32::IsWinNT Returns nonzero if the operating system is Windows NT: use Win32; $winnt = Win32::IsWinNT(); # true if running on Windows NT Win32::IsWin95 Returns nonzero if the operating system is Windows 95: use Win32; $win95 = Win32::IsWin95(); # true if running on Windows 95 Win32::ExpandEnvironmentStrings STRING Takes the STRING and builds a return string that has environment-variable strings replaced with their defined values: use Win32; $path = Win32::ExpandEnvironmentStrings('%PATH%'); # $path contains expanded PATH Win32::GetShortPathName LONGPATHNAME Returns the short (8.3) pathname for LONGPATHNAME: use Win32; $short = Win32::GetShortPathName('words.secret'); (WORDS~1.SEC) Win32::GetNextAvailDrive
Returns a string in the form of <d>:\ where <d> is the first available drive letter: use Win32; $drive = Win32::GetNextAvailDrive(); # $drive has first drive (e.g,. B:)
Previous: B.3 CPAN: Beyond the Standard Library Learning Perl on Win32 Systems Book Index Next: C. Networking Clients
C. Networking Clients
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Appendix C
C. Networking Clients
Contents: A Simple Client A Webget Client Few computers (or computer users, for that matter) are content to remain isolated from the rest of the world. Networking, once mostly limited to government research labs and computer science departments at major universities, is now available to virtually everyone, even home computer users with a modem and dial-up SLIP or PPP service. More than ever, networking is now used daily by organizations and individuals from every walk of life. They use networking to exchange email, schedule meetings, manage distributed databases, access company information, grab weather reports, pull down today's news, chat with someone in a different hemisphere, or advertise their company on the Web. These diverse applications all share one thing in common: they use TCP networking, the fundamental protocol that links the Net together.[1] And we don't just mean the Internet, either. Firewalls aside, the underlying technology is the same whether you're connecting far across the Internet, between your corporate offices, or from your kitchen down to your basement. As a result, you only have to learn one technology for all sorts of application areas. [1] Actually, IP (Internet Protocol) ties the Internet together, but TCP/IP is just a layer on top of IP. How can you use networking to let an application on one machine talk to a different application, possibly on a totally different machine? With Perl, it's pretty easy, but first you should probably know a little bit about how the TCP networking model works. Even if you've never touched a computer network before in your whole life, you already know another connection-based system: the telephone system. Don't let fancy words like "client-server programming" put you off. When you see the word "client," think "caller"; when you see the word "server," think "responder." If you ring someone up on the telephone, you are the client. Whoever picks up the phone at the other end is the server. Programmers with a background in C programming may be familiar with sockets. A socket is the interface to the network in the same sense that a filehandle is the interface to files in the filesystem. In fact, for the simple stream-based clients we're going to demonstrate below, you can use a socket handle
just as you would a filehandle.[2] [2] Well, almost; you can't seek on a socket. You can read from the socket, write to it, or both. That's because a socket is a special kind of bidirectional filehandle representing a network connection. Unlike normal files created via open, sockets are created using the low-level socket function. Let's squeeze a little more mileage out of our telephone model. When you call into a big company's telephone switchboard, you can ask for a particular department by one name or another (such as Personnel or Human Resources), or by an exact number (like extension 213). Think of each service running on a computer as a department in a large corporation. Sometimes a particular service has several different names, such as both http and www, but only one number, such as 80. That number associated with a particular service name is its port. The Perl functions getservbyname and getservbyport can be used to look up a service name given its port number, or vice versa. Table C.1 lists some standard TCP services and their port numbers. Table C.1: Standard TCP Services and Their Port Numbers Service Port Purpose echo 7 Accepts all input and echoes it back Accepts anything but does nothing with it Returns the current date and time in local format Server for file-transfer requests Server for interactive telnet sessions Simple mail transfer protocol; the mailer daemon Return number of seconds since 1900 (in binary) The World Wide Web server The news server
Although sockets were originally developed for Berkeley UNIX, the overwhelming popularity of the Internet has induced virtually all operating-systems vendors to include socket support for client-server programming. For this book, directly using the socket function is a bit low level. We recommend that you use the more user-friendly IO::Socket module,[3] which we'll use in all our sample code. Consequently, we'll also be employing some of Perl's object-oriented constructs. For a brief introduction to these constructs, see Chapter 18, CGI Programming. The perltoot documentation (starting with Perl 5.004) and Chapter 5 of Programming Perl offer a more complete introduction to object-oriented programming in Perl. [3] IO::Socket is included as part of the standard Perl distribution as of the 5.004 release and the current ActiveState at the time of this writing. If you're running an earlier version of
Perl, just fetch IO::Socket from CPAN. We don't have the space in this book to provide a full TCP/IP tutorial, but we can at least present a few simple clients. For servers, which are a bit more complicated, see Chapter 6 of Programming Perl. Generally speaking, writing servers in Perl on Windows NT is a difficult task because Perl doesn't currently offer support for threads, and there's no easy way to implement support for multiple simultaneous clients. This may change in the future, so stay tuned for future Perl releases.
worked, but numbers as constants make careful programmers nervous. [4] The system services file is in %windir%/system32/drivers/etc/services under Windows NT. Notice how the return value from the new constructor is used as a filehandle in the while loop? That example is an indirect filehandle, which is a scalar variable containing a filehandle. You can use this filehandle as you would a normal filehandle. For example, you can read one line from it this way: $line = <$handle>; Or all remaining lines from it this way: @lines = <$handle>; And send a line of data to it this way: print $handle "some data\n";
Previous: B.4 Win32 Extensions Learning Perl on Win32 Systems Book Index Next: C.2 A Webget Client
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Date: Thu, 08 May 1997 18:02:32 GMT Server: Apache/1.2b6 Connection: close Content-type: text/html <HEAD><TITLE>404 File Not Found</TITLE></HEAD> <BODY><H1>File Not Found</H1> The requested URL /guanaco.html was not found on this server.<P> </BODY> OK, so the program is not very interesting, because it didn't find that particular document. But a long response wouldn't have fit on this page. For a more full-featured version of this program, you should look for the lwp-request program included with the LWP modules from CPAN. You might also want to investigate the Win32::Internet extension module that provides easy access to the HTTP and FTP protocols. Win32::Internet is bundled with libwin32, or is available separately for those using the ActiveState distribution.
Previous: C.1 A Simple Client Learning Perl on Win32 Systems Book Index Next: D. Topics We Didn't Mention
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Appendix D
Book Index
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
chop($code = <STDIN>); eval $code; die "eval: $@" if $@; You can put Perl code inside the replacement string of a substitute operator with the e flag. This is handy if you want to construct something complicated for the replacement string, such as calling a subroutine that returns the results of a database lookup. Here's a loop that increments the value of the first column of a series of lines: while (<>) { s/^(\S+)/$1+1/e; # $1+1 is Perl code, not a string print; } Another use of eval is as an error-trapping mechanism: eval { &some_hairy_routine_that_might_die(@args); }; if ($@) { print "oops... some_hairy died with $@"; } Here, $@ will be empty as long as the eval block worked; otherwise, it will have the text of the die message.
Previous: D.4 Other Operators Learning Perl on Win32 Systems Book Index Next: D.6 Many, Many Predefined Variables
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
D.9 Packages
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
D.9 Packages
When multiple people work on a project, or if you're slighly schizophrenic, you can carve up the variable namespace using packages. A package is just a hidden prefix put in front of most variables (except variables created with the my operator). By changing the prefix, you get different variables. Here's a brief example: $a = 123; # this is really $main::a $main::a++; # same variable, now 124 package fred; # now the prefix is "fred" $a = 456; # this is $fred::a print $a - $main::a; # prints 456-124 package main; # back to original default print $a + $fred::a; # prints 124+456 So, any name with an explicit package name is used as is, but all other names get packaged into the current default package. Packages are local to the current file or block, and you always start out in package main at the top of a file. For details, the perlsub documentation will help here.
Previous: D.8 Additional Regular Expression Features Learning Perl on Win32 Systems Book Index Next: D.10 Embeddible, Extensible
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
included as part of the standard release. See the material in the perlfaq3 documentation about this.
D.9 Packages
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
logical not operator : 1.6.9. Making It a Bit More Modular [ (left bracket) in double-quoted strings : 3.7. Variable Interpolation of Arrays ^ (caret) as anchor in regular expressions : 7.3.3. Anchoring Patterns as filled-field in formats : 11.4.4. Filled Fields : (colon) label suffix : 9.4. Labeled Blocks matching with split( ) : 7.6.1. The split Function , (comma) array literal character : 3.2. Literal Representation operator : D.4. Other Operators {} (curly braces) in double-quoted strings : 2.6.4. Interpolation of Scalars into Strings in regular expressions : 7.3.2.2. Multipliers required in if statements : 4.2. The if/unless Statement $ (dollar sign) $1 as regular expression memory access : 7.4.5. Special Read-Only Variables $& (match string) : 7.4.5. Special Read-Only Variables $` (before-match string) : 7.4.5. Special Read-Only Variables $^ variable : 11.6.3. Changing the Top-of-Page Format Name $^I variable : 17.5. Variable-Length ( Text) Databases $^T variable : 10.6. The -x File Tests $: variable : 11.4.4. Filled Fields $= variable : 11.6.5. Changing the Position on the Page $- variable : 11.6.5. Changing the Position on the Page $% (special variable), example of : 1.6.14. Listing the Secret Words $#fred (index of last element of @fred) : 3.4.2. Array Element Access $' (after-match string) : 7.4.5. Special Read-Only Variables $/ variable : 6.1. Input from STDIN $~ variable : 11.6.2. Changing the Format Name $_ variable default for file tests : 10.6. The -x File Tests default for stat( ), lstat( ) : 10.7. The stat Function foreach statement and : 4.6. The foreach Statement
implicit assignment to when reading : 6.1. Input from STDIN regular expression matching default : 7.2. Simple Uses of Regular Expressions selecting other than with =~ operator : 7.4.1. Selecting a Different Target (the =~ Operator) split( ) default : 7.6.1. The split Function tr( ) default target : 15.5. Transliteration unlink( ) default : 13.1. Removing a File $a variable, as special in sort comparison routine : 15.4. Advanced Sorting $b variable, as special in sort comparison routine : 15.4. Advanced Sorting $_[0], distinct from $_ : 8.4. Arguments removing significance in strings : 2.6.4. Interpolation of Scalars into Strings scalar variable prefix : 2.5. Scalar Variables . (dot) .. list construction operator : 3.2. Literal Representation .= operator : 2.6.1. Binary Assignment Operators in regular expressions : 7.3.1. Single-Character Patterns = (equal sign) == operator : 2.4.2. Operators for Strings => operator (CGI) : 18.4.5. Fancier Calling Sequences =~ operator : 7.4.1. Selecting a Different Target (the =~ Operator) substitution and : 7.5. Substitutions array assignment operator : 3.4.1. Assignment assignment operator : 2.6. Scalar Operators and Functions =~ operator example of : 1.6.8. Making It Fair for the Rest tr( ) and : 15.5. Transliteration > (greater than) >= (greater than or equal to) operator : 2.4.2. Operators for Strings greater than operator : 2.4.2. Operators for Strings - (hyphen) -= operator : 11.4.2. Numeric Fields -- operator : 2.6.2. Autoincrement and Autodecrement in regular expression ranges : 7.3.1. Single-Character Patterns < (less than) <=> : (see spaceship (<=>) operator)
<> : (see diamond operator) <= (less than or equal to) operator : 2.4.2. Operators for Strings format field character : 11.4.1. Text Fields less than operator : 2.4.2. Operators for Strings ( ) (parentheses) array literals and : 3.2. Literal Representation as memory in regular expressions : 7.3.4. Precedence chdir( ) and : 12.1. Moving Around the Directory Tree forcing array context with : 3.4.1. Assignment keys( ) and : 5.4.1. The keys Function memory in regular expressions : 7.3.2.3. Parentheses as memory print( ) and : 6.3.1. Using print for Normal Output in regular expressions : 7.3.4. Precedence values( ) and : 5.4.2. The values Function % (percent sign) associative array prefix 1.6.6. Giving Each Person a Different Secret Word 5.2. Hash Variables modulus operator : 2.4.1. Operators for Numbers + (plus sign) += operator A.3. Chapter 4, Control Structures 2.6.1. Binary Assignment Operators ++ operator 2.6.2. Autoincrement and Autodecrement 14.1. Using system and exec open( ) and : 17.4. Fixed-Length Random-Access Databases in regular expressions : 7.3.2.2. Multipliers # (pound sign) comment character : 1.5. Basic Concepts format field characters : 11.4.2. Numeric Fields ? (question mark) in regular expressions : 7.3.2.2. Multipliers ?: operator, as control structure : 9.6. &&, ||, and ?: as Control Structures #!/usr/bin/perl line : 1.5. Basic Concepts
/ (slash) changing regular expressions : 7.4.3. Using a Different Delimiter choosing alternate to, in substitution : 7.5. Substitutions regular expression delimiter : 7.2. Simple Uses of Regular Expressions ~ (tilde) in formats : 11.4.4. Filled Fields | (vertical bar), open( ) and 1.6.12. Warning Someone When Things Go Astray 14.3. Using Processes as Filehandles | (vertical bar) format field characters : 11.4.1. Text Fields in regular expressions : 7.3.2.4. Alternation || (logical-or) operator as control structure : 9.6. &&, ||, and ?: as Control Structures die( ) and : 10.4. A Slight Diversion: die example of A.7. Chapter 8, Functions 15.4. Advanced Sorting introduced : 1.6.9. Making It a Bit More Modular
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: A
-A operator : 10.6. The -x File Tests Abba : 15.5. Transliteration AbortSystemShutdown module : B.4. Win32 Extensions access time, changing : 13.5. Modifying Timestamps Active Data Objects : 19.3.1. Data-Access Objects Active Message Library : 19.3. Using Automation Objects ActiveState : 1.3.1. ActiveState Perl for Win32 ActiveState Tool Corporation : 1.1. History of Perl ActiveX Data Objects : 17.6. Win32 Database Interfaces AddConnection : 12.5. Reading a Directory Handle addition, operator for : 2.4.1. Operators for Numbers address labels, and formats, examples of : 11.3. Invoking a Format AdminMisc module : B.4. Win32 Extensions ADO (ActiveX Data Objects) : 17.6. Win32 Database Interfaces alternation, in regular expressions : 7.3.2.4. Alternation anchoring, in regular expressions : 7.3.3. Anchoring Patterns angle brackets (<\>), as globbing delimiter : 12.2. Globbing appending to a file : 10.2. Opening and Closing a Filehandle archaeology : 15.2. Extracting and Replacing a Substring arguments, to subroutines : 8.4. Arguments @ARGV, as command-line arguments : 6.2. Input from the Diamond Operator array assignment operator : 3.4.1. Assignment array context, readdir( ) and : 12.5. Reading a Directory Handle array elements accessing : 1.6.5. More than One Secret Word numbering of : 3.4.2. Array Element Access
referencing : 3.4.2. Array Element Access array expression, as subscript : 3.4.2. Array Element Access array literals, defined : 3.2. Literal Representation array operators : 3.4. Array Operators and Functions array slice : 3.4.2. Array Element Access array variables : 3.3. Variables assigned scalar values : 3.4.1. Assignment automatically growing : 3.4.2. Array Element Access default value of : 3.3. Variables foreach statement : 4.6. The foreach Statement in array literals : 3.4.1. Assignment in scalar context : 3.4.1. Assignment interpolated into strings : 3.7. Variable Interpolation of Arrays arrays 1.6.5. More than One Secret Word 3.1. What Is a List or Array? empty : 3.2. Literal Representation referencing elements : 3.4.2. Array Element Access size boundaries : 3.1. What Is a List or Array? Artistic License : 1.3. Availability assigning to a substr( ) : 15.2. Extracting and Replacing a Substring assigning to an array : 1.6.5. More than One Secret Word assignment operator : 2.6. Scalar Operators and Functions assignment, binary : 2.6.1. Binary Assignment Operators associative arrays variables : 5.2. Hash Variables associativity : 2.4.3. Operator Precedence and Associativity Astro, pronouncing "Windex" : 15.1. Finding a Substring attrib command : (see chmod command) autodecrement operator : 2.6.2. Autoincrement and Autodecrement autoincrement : 4.5. The for Statement operator : 2.6.2. Autoincrement and Autodecrement
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: B
-B operator : 10.6. The -x File Tests \B, as anchor in regular expressions : 7.3.3. Anchoring Patterns \b, example of : 7.4.4. Using Variable Interpolation \ (backslash) before dollar in regular expression : 7.3.3. Anchoring Patterns backtracking, in regular expressions : 7.3.2.2. Multipliers backup files, and inplace editing : 17.5. Variable-Length ( Text) Databases \ (backslash) in regular expressions as memory access : 7.3.2.3. Parentheses as memory basename command, emulating : A.12. Chapter 13, File and Directory Manipulation big-endian : 16.2. Packing and Unpacking Binary Data binary assignment operator : 2.6.1. Binary Assignment Operators binary data, treated, using strings : 2.3. Strings binmode( ) : 17.4. Fixed-Length Random-Access Databases blocks 1.6.3. Adding Choices 4.1. Statement Blocks as body of subroutine 1.6.9. Making It a Bit More Modular 8.1. Defining a User Function labeled : 9.4. Labeled Blocks looping : 9.1. The last Statement naked : 9.1. The last Statement break (in C), and last operator : 9.1. The last Statement BuildNumber module : B.4. Win32 Extensions built-in variables : D.6. Many, Many Predefined Variables
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: C
-C operator : 10.6. The -x File Tests c, as complement option of tr : 15.5. Transliteration cacls.exe program : 13.4. Modifying Permissions Camel Book D.5. Many, Many More Functions 1.4. Support 16.2. Packing and Unpacking Binary Data 17.5. Variable-Length ( Text) Databases canonical name, from gethostbyname( ) : 16.3. Getting Network Information case ignoring 1.6.7. Handling Varying Input Formats 7.5. Substitutions in variable names : 2.5. Scalar Variables cd command : 12.1. Moving Around the Directory Tree CGI Programming : 18. CGI Programming CGI.pm module : 18.1. The CGI.pm Module ChangeNotify module : B.4. Win32 Extensions changing directories : 12.1. Moving Around the Directory Tree character classes, in regular expressions : 7.3.1. Single-Character Patterns character ranges, in regular expressions : 7.3.1. Single-Character Patterns chdir( ) : 12.1. Moving Around the Directory Tree example of : A.11. Chapter 12, Directory Access Chili's : Acknowledgments for First Edition chmod command, and the chmod( ) : 13.4. Modifying Permissions chmod( ) : 13.4. Modifying Permissions chomp( )
1.6.2. Asking Questions and Remembering the Result 3.4.7. The chomp Function examples of 1.6.10. Moving the Secret Word List into a Separate File 1.6.17. The Final Programs 10.5. Using Filehandles chop( ) : 2.6.3. The chop( ) and chomp( ) Functions examples of A.1. Chapter 2, Scalar Data 2.7. <STDIN> as a Scalar Value chr( ) : 16.2. Packing and Unpacking Binary Data circle, circumference of : 2.10. Exercises clients, networking : C. Networking Clients Clipboard module : B.4. Win32 Extensions close( ) : 10.2. Opening and Closing a Filehandle examples of : 1.6.10. Moving the Secret Word List into a Separate File process-filehandles : 14.3. Using Processes as Filehandles closedir( ) : 12.4. Opening and Closing a Directory Handle example of : A.11. Chapter 12, Directory Access CLSID : 19.2. Creating Automation Objects cmp operator : 15.4. Advanced Sorting COBOL : 11.1. What Is a Format? Coke : 2.3.2. Double-Quoted Strings column headers, in format : 11.1. What Is a Format? columns, labeling : 1.6.14. Listing the Secret Words command line : D.3. The Command Line command-line arguments : 17.5. Variable-Length ( Text) Databases diamond operator and : 6.2. Input from the Diamond Operator comments, in Perl programs : 1.5. Basic Concepts comparison operators : 2.4.2. Operators for Strings comparison routine, in sorting : 15.4. Advanced Sorting compiled language, Perl as a : 1.5. Basic Concepts concatenation : 2.4.2. Operators for Strings
Console module : B.4. Win32 Extensions constant part : 11.1. What Is a Format? context, scalar and array : 3.5. Scalar and List Context continue block : 9.2. The next Statement control expression of if statement : 4.2. The if/unless Statement while statements : 4.3. The while/until Statement Control-D, as end of file : 3.6. <STDIN> as an Array copy pass : 17.5. Variable-Length ( Text) Databases counting characters : 15.5. Transliteration CPAN (Comprehensive Perl Archive Network) : B.3. CPAN: Beyond the Standard Library Create( ) : 16.5. Opening and Reading Registry Values CreateObject( ) 19.2. Creating Automation Objects 19.3. Using Automation Objects creating processes : 14.1. Using system and exec currently selected filehandle : 11.6.1. Using select to Change the Filehandle
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: D
-d operator : 10.6. The -x File Tests d, as delete option of tr : 15.5. Transliteration \d, in regular expressions : 7.3.1. Single-Character Patterns dangling else, and impossibility of : 4.2. The if/unless Statement database interface modules : B.2.6. Database Interfaces databases fixed-length records in : 17.4. Fixed-Length Random-Access Databases human-readable : 17.5. Variable-Length ( Text) Databases managing with the DBM library : 17.1. DBM Databases and DBM Hashes random-access : 17.4. Fixed-Length Random-Access Databases daytime server : C.1. A Simple Client DBM array : 17.1. DBM Databases and DBM Hashes DBM files : 1.6.16. Maintaining a Last-Good-Guess Database DBM library : 17.1. DBM Databases and DBM Hashes dbmclose( ) : 17.2. Opening and Closing DBM Hashes example of : 1.6.17. The Final Programs dbmopen( ) : 17.2. Opening and Closing DBM Hashes examples of 1.6.17. The Final Programs 1.6.16. Maintaining a Last-Good-Guess Database debugger : D.2. The Debugger decimal points, in floating-point numbers : 2.2.2. Float Literals default filehandle : 10.5. Using Filehandles default values, implemented with || operator : 1.6.9. Making It a Bit More Modular defensive programming : 15.4. Advanced Sorting defining a format : 11.2. Defining a Format
delete operator : 5.4.4. The delete Function delete( ), example of : 17.3. Using a DBM Hash DeleteKey( ) : 16.6.1. More Registry Operations deleting characters : 15.5. Transliteration deleting Registry keys : 16.6.1. More Registry Operations delimiters, for tr : 15.5. Transliteration diamond operator (<>) 6.2. Input from the Diamond Operator 17.5. Variable-Length ( Text) Databases examples of A.7. Chapter 8, Functions A.9. Chapter 10, Filehandles and File Tests A.14. Chapter 15, Other Data Transformation A.16. Chapter 17, Database Manipulation 7.2. Simple Uses of Regular Expressions die( ) : 10.4. A Slight Diversion: die examples of : A.11. Chapter 12, Directory Access using : 1.6.13. Many Secret Word Files in the Current Directory directories, renaming files into : 13.2. Renaming a File directory handles : 12.3. Directory Handles creating : 12.4. Opening and Closing a Directory Handle division, operators for : 2.4.1. Operators for Numbers Documentation : 1.5.1. Documentation documentation : 1.5.1. Documentation DomainName module : B.4. Win32 Extensions dot (.) as current directory : A.11. Chapter 12, Directory Access example of : A.7. Chapter 8, Functions double-quote interpolation : (see variable interpolation) double-quoted strings : 2.3.2. Double-Quoted Strings backslash escape and : 2.3.2. Double-Quoted Strings example of : 1.6.2. Asking Questions and Remembering the Result hash elements : 5.4.1. The keys Function
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: E
-e command-line option, and inplace editing : 17.5. Variable-Length ( Text) Databases -e operator : 10.6. The -x File Tests e, as option to substitute operator : D.5.2. The eval Operator (and s///e) each( ) : 5.4.3. The each Function examples of : 17.3. Using a DBM Hash echo command, and globbing : 12.2. Globbing editors, and updating databases : 17.5. Variable-Length ( Text) Databases elements of array : 3.1. What Is a List or Array? else keyword : 4.2. The if/unless Statement elsif keyword 1.6.5. More than One Secret Word 4.2. The if/unless Statement example of A.3. Chapter 4, Control Structures 15.4. Advanced Sorting email, example of handling : 9.1. The last Statement embedding Perl : D.10. Embeddible, Extensible empty array : 3.2. Literal Representation empty list : 3.2. Literal Representation as default value for array variable : 3.3. Variables clearing out a hash : 5.4.2. The values Function end of file detecting, introduced : 1.6.10. Moving the Secret Word List into a Separate File with Control-D : 3.6. <STDIN> as an Array %ENV variable : 14.1. Using system and exec environment variables, controlling through %ENV : 14.1. Using system and exec eq operator : 2.4.2. Operators for Strings
example of 1.6.3. Adding Choices 1.6.17. The Final Programs Error module : B.4. Win32 Extensions eval( ) D.5.2. The eval Operator (and s///e) 11.1. What Is a Format? EventLog module : B.4. Win32 Extensions examples, where to get on-line : Exercises execute bits : 13.4. Modifying Permissions exit status, die( ) and : 10.4. A Slight Diversion: die exit value : 14.3. Using Processes as Filehandles exit( ) : 14.3. Using Processes as Filehandles ExpandEnvironmentStrings module : B.4. Win32 Extensions experts, and reading introductory sections : 1.6.8. Making It Fair for the Rest exponential notation, in floating-point numbers : 2.2.2. Float Literals exponentiation operator (**) : 2.4.1. Operators for Numbers expressions in a subroutine body : 8.3. Return Values in array literals : 3.2. Literal Representation extension modules definition of : B.1. Library Terminology Win32, list of : B.4. Win32 Extensions
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: F
-f operator : 10.6. The -x File Tests false : 4.2. The if/unless Statement regular expressions : 7.2. Simple Uses of Regular Expressions FAQ, Perl : 1.4. Support field definition line, introduced : 1.6.14. Listing the Secret Words field value line, introduced : 1.6.14. Listing the Secret Words fieldlines of format : 11.2. Defining a Format File module B.4. Win32 Extensions 13.4. Modifying Permissions File::Basename : 10.3. Using Pathnames and Filenames filehandles 1.6.10. Moving the Secret Word List into a Separate File 10.1. What Is a Filehandle? default, defined : 10.5. Using Filehandles formats and : 11.3. Invoking a Format indirect : 12.2. Globbing print( ) and : 1.6.12. Warning Someone When Things Go Astray as processes : 14.3. Using Processes as Filehandles read( ) and : 17.4. Fixed-Length Random-Access Databases reading from : 10.5. Using Filehandles seek( ) and : 17.4. Fixed-Length Random-Access Databases as uppercase : 1.6.10. Moving the Secret Word List into a Separate File filename glob : 1.6.13. Many Secret Word Files in the Current Directory filenames : 10.3. Using Pathnames and Filenames files age, example of : 1.6.11. Ensuring a Modest Amount of Security
appending to : 10.2. Opening and Closing a Filehandle information about, with stat( ) : 10.7. The stat Function modifying permissions of : 13.4. Modifying Permissions modifying timestamps of : 13.5. Modifying Timestamps opening : 10.2. Opening and Closing a Filehandle removing : 13.1. Removing a File renaming 1.6.15. Making Those Old Word Lists More Noticeable 13.2. Renaming a File testing for existence : 10.6. The -x File Tests FileSecurity module B.4. Win32 Extensions 13.4. Modifying Permissions filled fields, in formats : 11.4.4. Filled Fields finding a substring : 15.1. Finding a Substring finding a substring in reverse : 15.1. Finding a Substring findstr command : 7.2. Simple Uses of Regular Expressions ignoring case : 7.4.2. Ignoring Case floating-point literals : 2.2.2. Float Literals floating-point numbers : 2.2.1. All Numbers Use the Same Format Internally footnotes, meaning of : Conventions for statement : 4.5. The for Statement example of A.3. Chapter 4, Control Structures 9.4. Labeled Blocks foreach statement 1.6.16. Maintaining a Last-Good-Guess Database 4.6. The foreach Statement example of A.3. Chapter 4, Control Structures A.4. Chapter 5, Hashes A.11. Chapter 12, Directory Access 1.6.17. The Final Programs
12.5. Reading a Directory Handle 17.3. Using a DBM Hash foreach( ), example of : A.5. Chapter 6, Basic I/O format definition example of : 1.6.14. Listing the Secret Words location in source file : 11.2. Defining a Format format fieldholders : 11.2. Defining a Format format fieldlines : 11.2. Defining a Format format keyword 1.6.14. Listing the Secret Words 11.2. Defining a Format example of : 1.6.17. The Final Programs format names changing : 11.6.2. Changing the Format Name selecting : 11.2. Defining a Format format template : 11.2. Defining a Format FormatMessage module : B.4. Win32 Extensions formats : 11.1. What Is a Format? changing top-of-page format name : 11.6.3. Changing the Top-of-Page Format Name constant part : 11.1. What Is a Format? defining : 11.2. Defining a Format defining text fields : 11.4.1. Text Fields invoking : 11.3. Invoking a Format multi-line fieldholder defined : 11.4.3. Multiline Fields top-of-page : 11.5. The Top-of-Page Format variable part : 11.1. What Is a Format? whitespace within : 11.2. Defining a Format formatted output, printf( ) and : 6.3.2. Using printf for Formatted Output formfeed, and top-of-page format : 11.5. The Top-of-Page Format FsType function : 10.7. The stat Function FsType module : B.4. Win32 Extensions FTP, obtaining exercises via : FTP FTPMAIL : FTPMAIL
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: G
g as global replace option : 7.5. Substitutions modifier of regexp match : D.4. Other Operators GetCwd function : 12.1. Moving Around the Directory Tree GetCwd module : B.4. Win32 Extensions GetFileAttributes method : 13.4. Modifying Permissions gethostbyname( ) : 16.3. Getting Network Information GetLastError module : B.4. Win32 Extensions GetNextAvailDrive module : B.4. Win32 Extensions getopt, and the Perl standard library : 6.2. Input from the Diamond Operator GetOSVersion module : B.4. Win32 Extensions getservbyname( ) : C. Networking Clients getservbyport( ) : C. Networking Clients GetShortPathName function : 10.3. Using Pathnames and Filenames GetShortPathName module : B.4. Win32 Extensions GetTickCount module : B.4. Win32 Extensions GetValues method : 16.5. Opening and Reading Registry Values glob : 1.6.13. Many Secret Word Files in the Current Directory global replace example of : A.9. Chapter 10, Filehandles and File Tests in substitute operator : 7.5. Substitutions global variables, and subroutines : 8.1. Defining a User Function globbing : 12.2. Globbing compared with regular expressions : 12.2. Globbing example of, with unlink( ) : 13.1. Removing a File variable interpolation : 12.2. Globbing
GNU Public License : 1.3. Availability goto, unnecessary in Perl : 9.4. Labeled Blocks greediness in regular expression patterns : 7.3.2.2. Multipliers in regular expressions : 7.3.2.2. Multipliers grep function : D.5.1. grep and map gt operator : 2.4.2. Operators for Strings gzip utility : 1.3.2. Standard Perl Distribution
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: H
hash : 1.6.6. Giving Each Person a Different Secret Word hash keys : 1.6.6. Giving Each Person a Different Secret Word hash operators : 5.4. Hash Functions hashes : 5.1. What Is a Hash? creating new elements of : 5.2. Hash Variables example of assignment to : 1.6.6. Giving Each Person a Different Secret Word literal representation of : 5.3. Literal Representation of a Hash order in : 5.1. What Is a Hash? removing elements from with delete : 5.4.4. The delete Function sorting (sort-of) : 15.4. Advanced Sorting stepping through with the each( ) : 5.4.3. The each Function Hello, world (program example) : 1.6.1. The "Hello, world" Program help documentation : 1.5.1. Documentation technical support : 1.4. Support here strings : 2.3. Strings hex( ) 2.2.3. Integer Literals 2.4.4. Conversion Between Numbers and Strings hexadecimal numbers : 2.2.3. Integer Literals hives, Registry : 16.4.1. The Registry Structure HKEY_LOCAL_MACHINE subtree : 16.4.1. The Registry Structure human-readable databases : 17.5. Variable-Length ( Text) Databases
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
[ Library Home | Perl in a Nutshell | Learning Perl | Learning Perl on Win32 | Programming Perl | Advanced Perl Programming | Perl Cookbook ]
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: I
-i option for inplace editing : 17.5. Variable-Length ( Text) Databases -i option for inplace editing : 17.5. Variable-Length ( Text) Databases -i flag (ignore case) : 7.5. Substitutions i flag (ignore case) : 7.4.2. Ignoring Case if modifier : 9.5. Expression Modifiers if statement 1.6.3. Adding Choices 4.2. The if/unless Statement example of 1.6.17. The Final Programs 1.6.9. Making It a Bit More Modular 4.2. The if/unless Statement 5.4.1. The keys Function not counting as looping block : 9.2. The next Statement ignoring case example of : 1.6.7. Handling Varying Input Formats in substitution : 7.5. Substitutions with i flag : 7.4.2. Ignoring Case in-proc servers : 19.1. Introduction to OLE Automation indentation, in Perl programs : 1.5. Basic Concepts index( ) : 15.1. Finding a Substring indirect filehandles : 12.2. Globbing infinite loops : 9.3. The redo Statement InitiateSystemShutdown module : B.4. Win32 Extensions inplace editing : 17.5. Variable-Length ( Text) Databases int( ) : 10.6. The -x File Tests integer : 2.2.3. Integer Literals
integers : 2.2.1. All Numbers Use the Same Format Internally Internet module : B.4. Win32 Extensions interpreted language, Perl as a : 1.5. Basic Concepts interpreted languages : 1.1. History of Perl interpreting bytes in memory : 16.2. Packing and Unpacking Binary Data Introduction to OLE Automation : 19.1. Introduction to OLE Automation invoking a format : 11.3. Invoking a Format invoking a subroutine : 8.2. Invoking a User Function IO::Socket module : C. Networking Clients IPC module : B.4. Win32 Extensions ISAP : 1.3.1. ActiveState Perl for Win32 ISAPI extensions : 18.7.2. PerlIS and PerlScript IsWin95 module : B.4. Win32 Extensions IsWinNT module : B.4. Win32 Extensions
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: J
join( ) : 7.6.2. The join Function example of : 16.3. Getting Network Information
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: K
keys( ) 1.6.13. Many Secret Word Files in the Current Directory 1.6.16. Maintaining a Last-Good-Guess Database 5.4.1. The keys Function scalar context and : 5.4.1. The keys Function keys, of hashes : 5.1. What Is a Hash? keys, Registry : 16.4.1. The Registry Structure kit'n'caboodle : 15.4. Advanced Sorting kludge : 9.4. Labeled Blocks
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: L
labels : 9.4. Labeled Blocks language extension modules : B.2.14. For Developers: Language Extensions and Platform Development Support last access time, changing : 13.5. Modifying Timestamps last modification time, changing : 13.5. Modifying Timestamps last operator : 9.1. The last Statement example of : A.8. Chapter 9, Miscellaneous Control Structures last( ), example of : 9.5. Expression Modifiers le operator : 2.4.2. Operators for Strings left associativity : 2.4.3. Operator Precedence and Associativity left-right pairs as delimiters : 7.4.3. Using a Different Delimiter length( ), example of : 17.4. Fixed-Length Random-Access Databases libraries, definition of : B.1. Library Terminology libwin32 package : 1.3.2. Standard Perl Distribution link( ) : 13. File and Directory Manipulation list (see also arrays) 1.6.5. More than One Secret Word 3.1. What Is a List or Array? list constructor operator (..) : 3.2. Literal Representation list expressions, and foreach statement : 4.6. The foreach Statement list reference (in Perl 5.0) : 3.4.1. Assignment listing the /etc directory, example of : 12.5. Reading a Directory Handle lists nested : 3.4.1. Assignment as subroutine return values : 8.3. Return Values
literal lists, slices of : 3.4.2. Array Element Access literals, array : 3.2. Literal Representation literals, of hashes : 5.3. Literal Representation of a Hash little-endian : 16.2. Packing and Unpacking Binary Data local( ) example of A.7. Chapter 8, Functions 11.4.2. Numeric Fields loops and : 8.5. Private Variables in Functions local servers : 19.1. Introduction to OLE Automation local variables creating, with local( ) : 8.5. Private Variables in Functions foreach statement : 4.6. The foreach Statement in subroutines, example of : 8.4. Arguments logical comparison operators : 2.4.1. Operators for Numbers logical not (!) operator : 1.6.9. Making It a Bit More Modular LoginName function : 16.1. Getting User and Machine Information LoginName module : B.4. Win32 Extensions LookupAccountName module : B.4. Win32 Extensions LookupAccountSID module : B.4. Win32 Extensions looping blocks : 9.1. The last Statement loops endless : 4.3. The while/until Statement exiting early, with last : 9.1. The last Statement infinite : 9.3. The redo Statement local( ) and : 8.5. Private Variables in Functions nested, exiting from : 9.4. Labeled Blocks lowercase, example of converting to : 1.6.8. Making It Fair for the Rest lpr command, example of : 14.3. Using Processes as Filehandles lt operator : 2.4.2. Operators for Strings lvalue : 3.4.1. Assignment
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: M
-M operator : 10.6. The -x File Tests example of : 1.6.11. Ensuring a Modest Amount of Security m, as match operator : 7.4.3. Using a Different Delimiter mailing lists, Perl : 1.4. Support main routine, unneeded in Perl : 1.5. Basic Concepts map operator : D.5.1. grep and map MAPI : 19.3. Using Automation Objects match operator : 7.2. Simple Uses of Regular Expressions example of : 1.6.7. Handling Varying Input Formats matching, choosing a delimiter besides slash : 7.4.3. Using a Different Delimiter mathematics modules : B.2.7. Mathematics Max Headroom : 13.5. Modifying Timestamps McMenamin's : Acknowledgments for First Edition memory, interpeting bytes in : 16.2. Packing and Unpacking Binary Data methods : 19.1. Introduction to OLE Automation microbrew : Acknowledgments for First Edition mkdir command, mkdir( ) and : 13.3. Making and Removing Directories modes, and making directories : 13.3. Making and Removing Directories modification time changing : 13.5. Modifying Timestamps example of : 1.6.11. Ensuring a Modest Amount of Security modules, definition of : B.1. Library Terminology modules, list of : B.2. Standard Modules Win32 extensions : B.4. Win32 Extensions modulus operator (%) : 2.4.1. Operators for Numbers multi-line fieldholder, in formats : 11.4.3. Multiline Fields
multiplication, operator for : 2.4.1. Operators for Numbers Mutex module : B.4. Win32 Extensions mv command, rename( ) and : 13.2. Renaming a File
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: N
\n, in single-quoted strings : 2.3.1. Single-Quoted Strings naked blocks : 9.1. The last Statement name spaces : 3.3. Variables naming subroutine arguments, using local variables : 8.5. Private Variables in Functions ne operator : 2.4.2. Operators for Strings example of : 1.6.4. Guessing the Secret Word nested loops, exiting from : 9.4. Labeled Blocks nested subroutine invocation : 8.2. Invoking a User Function net use : 12.5. Reading a Directory Handle net view : 14.6. Exercises NetAdmin module B.4. Win32 Extensions 16.1. Getting User and Machine Information NetResource module B.4. Win32 Extensions 12.5. Reading a Directory Handle netstat : 14.3. Using Processes as Filehandles networking : C. Networking Clients newlines in format value, and @* field : 11.4.3. Multiline Fields non-matching by dot : 7.3.1. Single-Character Patterns removing : 2.7. <STDIN> as a Scalar Value newsgroup, Perl : 1.4. Support next operator : 9.2. The next Statement NodeName function : 16.1. Getting User and Machine Information NodeName module : B.4. Win32 Extensions numbers : 2.1. What Is Scalar Data?
automatic conversion to strings : 2.4.4. Conversion Between Numbers and Strings numeric fields (in formats) : 11.4.2. Numeric Fields numeric operators : 2.4.1. Operators for Numbers numeric order, example of sorting by : 15.4. Advanced Sorting
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: O
obscure biblical reference : 15.5. Transliteration oct( ) 2.2.3. Integer Literals 2.4.4. Conversion Between Numbers and Strings octal numbers, defined : 2.2.3. Integer Literals OCX controls : 19.1. Introduction to OLE Automation ODBC module B.4. Win32 Extensions 17.6. Win32 Database Interfaces OLE module A.18. Chapter 19, OLE Automation B.4. Win32 Extensions 19.2. Creating Automation Objects OLEDB : 19.3.1. Data-Access Objects Open( ) : 16.5. Opening and Reading Registry Values open( ) : 10.2. Opening and Closing a Filehandle commands and, example of : 1.6.17. The Final Programs example of A.9. Chapter 10, Filehandles and File Tests 11.3. Invoking a Format introduced : 1.6.10. Moving the Secret Word List into a Separate File plus sign and : 17.4. Fixed-Length Random-Access Databases vertical bar in : 14.3. Using Processes as Filehandles vertical bar in : 1.6.12. Warning Someone When Things Go Astray opendir( ) 12.4. Opening and Closing a Directory Handle 12.5. Reading a Directory Handle
example of : A.11. Chapter 12, Directory Access opening DBM database : 17.2. Opening and Closing DBM Hashes files : 10.2. Opening and Closing a Filehandle Registry values : 16.5. Opening and Reading Registry Values operands, defined : 2.4. Scalar Operators operators : 2.4. Scalar Operators addition : 2.4.1. Operators for Numbers assignment : 2.6. Scalar Operators and Functions associativity : 2.4.3. Operator Precedence and Associativity autodecrement : 2.6.2. Autoincrement and Autodecrement autoincrement : 2.6.2. Autoincrement and Autodecrement division : 2.4.1. Operators for Numbers for hashes : 5.4. Hash Functions logical comparison : 2.4.1. Operators for Numbers multiplication : 2.4.1. Operators for Numbers precedence of : 2.4.3. Operator Precedence and Associativity for scalar variables : 2.6. Scalar Operators and Functions for strings : 2.4.2. Operators for Strings subtraction : 2.4.1. Operators for Numbers undef and : 2.9. The Undefined Value ord( ) : 16.2. Packing and Unpacking Binary Data
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: P
-p command-line option, and inplace editing : 17.5. Variable-Length ( Text) Databases pack( ) : 16.2. Packing and Unpacking Binary Data example of : 17.4. Fixed-Length Random-Access Databases pack format string : 16.2. Packing and Unpacking Binary Data packages B.1. Library Terminology D.9. Packages page length changing, in formats : 11.6.4. Changing the Page Length default, for top-of-page format : 11.5. The Top-of-Page Format page position, changing, in formats : 11.6.5. Changing the Position on the Page parameters, introduced : 1.6.9. Making It a Bit More Modular parentheses precedence and : 2.4.3. Operator Precedence and Associativity path delimiter : 10.3. Using Pathnames and Filenames PATH environment variable, managing : 14.1. Using system and exec pathnames 2.3.2. Double-Quoted Strings 10.3. Using Pathnames and Filenames Perl embedding : D.10. Embeddible, Extensible history of : 1.1. History of Perl standard distribution of : 1.3.2. Standard Perl Distribution technical support : 1.4. Support Perl compiler : D.10.4. The Perl Compiler Perl for Win32 : 1.3.1. ActiveState Perl for Win32 Perl standard library : 6.2. Input from the Diamond Operator
Perl: The Motion Picture : 16.2. Packing and Unpacking Binary Data perldoc command : 1.5.1. Documentation PerlIIS extension : 18.7.2. PerlIS and PerlScript PerlIS : 1.3.1. ActiveState Perl for Win32 PerlScript 1.3.1. ActiveState Perl for Win32 18.7.2. PerlIS and PerlScript permissions 1.6.16. Maintaining a Last-Good-Guess Database 13.4. Modifying Permissions modifying : 13.4. Modifying Permissions permission bits, in dbmopen( ) : 17.2. Opening and Closing DBM Hashes pi computing with : A.1. Chapter 2, Scalar Data obscure reference to : 16.2. Packing and Unpacking Binary Data pipe : (see | (vertical bar)) Pipe module : B.4. Win32 Extensions .plx extension : 1.5. Basic Concepts pod : 18.1. The CGI.pm Module POD : 1.5.1. Documentation pointers : D.10.7. Function Pointers pop( ) : 3.4.3. The push and pop Functions example of : A.3. Chapter 4, Control Structures popen library function, emulating : 14.3. Using Processes as Filehandles port numbers : C. Networking Clients powers of ten, example of, with substr( ) : 15.2. Extracting and Replacing a Substring Practical Extraction and Report Language : 11.1. What Is a Format? pragmas, definition of : B.1. Library Terminology precedence : 2.4.3. Operator Precedence and Associativity in regular expressions : 7.3.4. Precedence parentheses and : 2.4.3. Operator Precedence and Associativity predefined variables : D.6. Many, Many Predefined Variables print( )
2.8. Output with print 6.3.1. Using print for Normal Output 17.4. Fixed-Length Random-Access Databases $_ and : 4.6. The foreach Statement array literals and : 3.2. Literal Representation example of 1.6.1. The "Hello, world" Program 1.6.17. The Final Programs filehandle keyword and : 1.6.12. Warning Someone When Things Go Astray return value of : 6.3.1. Using print for Normal Output writes to same filehandle and : 11.5. The Top-of-Page Format printf( ) : 6.3.2. Using printf for Formatted Output example of A.3. Chapter 4, Control Structures A.5. Chapter 6, Basic I/O 4.7. Exercises process exit value : 14.3. Using Processes as Filehandles process launching : 14.4. Summary of Process Operations Process module B.4. Win32 Extensions 14.5. Win32::Process processes creating : 14.1. Using system and exec as filehandles : 14.3. Using Processes as Filehandles Windows NT and : 14.5. Win32::Process products, finding : 9.4. Labeled Blocks ProgID 19.2. Creating Automation Objects 19.3. Using Automation Objects Programming Perl : (see Camel Book) prompt, example of : 1.6.2. Asking Questions and Remembering the Result properties : 19.1. Introduction to OLE Automation push( ) : 3.4.3. The push and pop Functions pwd command : 12.1. Moving Around the Directory Tree
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: Q
qw( ) 1.6.5. More than One Secret Word 18.4. Passing Parameters via CGI
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: R
-r operator : 10.6. The -x File Tests rand( ) : 3.8. Exercises example of : A.2. Chapter 3, Arrays and List Data random access, seek( ) and : 17.4. Fixed-Length Random-Access Databases ranges of characters : 7.3.1. Single-Character Patterns read( ) : 17.4. Fixed-Length Random-Access Databases readdir( ) : 12.5. Reading a Directory Handle reading data from a command : 14.3. Using Processes as Filehandles reading from a file : 10.5. Using Filehandles reading from standard input : 6.1. Input from STDIN reading Registry values : 16.5. Opening and Reading Registry Values redo operator : 9.3. The redo Statement regedit.exe, regedt32.exe utilities : 16.4. The Registry Registry module A.15. Chapter 16, System Information B.4. Win32 Extensions Registry package 16.4. The Registry 16.4.1. The Registry Structure Registry, Windows NT : 16.4. The Registry regular expressions 1.6.7. Handling Varying Input Formats 7.1. Concepts About Regular Expressions alternation in : 7.3.2.4. Alternation anchoring in : 7.3.3. Anchoring Patterns backtracking in : 7.3.2.2. Multipliers character classes in : 7.3.1. Single-Character Patterns
compared with globbing : 12.2. Globbing example of 1.6.8. Making It Fair for the Rest 1.6.9. Making It a Bit More Modular 9.1. The last Statement extended syntax : D.8. Additional Regular Expression Features grouping patterns of : 7.3.2. Grouping Patterns non-special characters of : 7.3.1. Single-Character Patterns precedence in : 7.3.4. Precedence split( ) and : 7.6.1. The split Function variable interpolation : 7.4.4. Using Variable Interpolation removing a file : 13.1. Removing a File removing characters : 15.5. Transliteration removing the last character : 2.6.3. The chop( ) and chomp( ) Functions rename command (Windows NT) : 13.2. Renaming a File rename( ) 1.6.15. Making Those Old Word Lists More Noticeable 13.2. Renaming a File example of : A.12. Chapter 13, File and Directory Manipulation renaming files : 13.2. Renaming a File examples of : 1.6.15. Making Those Old Word Lists More Noticeable report generating, example of : 1.6.14. Listing the Secret Words reports, writing : 11.1. What Is a Format? result : 2.4. Scalar Operators return status, backwards for system( ) : 14.1. Using system and exec return values : 1.6.9. Making It a Bit More Modular from subroutine, example of : 1.6.17. The Final Programs of tr : 15.5. Transliteration print( ) and : 6.3.1. Using print for Normal Output read( ) and : 17.4. Fixed-Length Random-Access Databases of select( ) : 11.6.1. Using select to Change the Filehandle subroutines : 8.3. Return Values reverse( ) : 3.4.5. The reverse Function
example of A.2. Chapter 3, Arrays and List Data A.5. Chapter 6, Basic I/O right angle brackets (\>), as format field characters : 11.4.1. Text Fields right associativity : 2.4.3. Operator Precedence and Associativity rindex( ) : 15.1. Finding a Substring example of : A.14. Chapter 15, Other Data Transformation rm command, unlink( ) and : 13.1. Removing a File rmdir command, and rmdir( ) : 13.3. Making and Removing Directories
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: S
s operator example of 1.6.17. The Final Programs 12.2. Globbing making basename of file and : A.12. Chapter 13, File and Directory Manipulation substitute operator : 7.5. Substitutions -s operator : 10.6. The -x File Tests s option, tr( ) : 15.5. Transliteration \s, in regular expressions : 7.3.1. Single-Character Patterns scalar assignment, used as a value : 2.6. Scalar Operators and Functions scalar context 3.4.1. Assignment 3.5. Scalar and List Context readdir( ) : 12.5. Reading a Directory Handle scalar data : 2.1. What Is Scalar Data? scalar values, assigned to array variables : 3.4.1. Assignment scalar variables 1.6.2. Asking Questions and Remembering the Result 2.5. Scalar Variables operators for : 2.6. Scalar Operators and Functions scientific notation, in floating-point numbers : 2.2.2. Float Literals Scooby Doo, pronouncing "Windex" : 15.1. Finding a Substring secret words, guessing : 1.6.4. Guessing the Secret Word security : D.10.1. Security Matters seek( ) : 17.4. Fixed-Length Random-Access Databases select( ) : 11.6.1. Using select to Change the Filehandle return value of : 11.6.1. Using select to Change the Filehandle
Semaphore module : B.4. Win32 Extensions semicolon (;), as statement terminator : 1.6.1. The "Hello, world" Program sequence, in regular expressions : 7.3.2.1. Sequence Service module : B.4. Win32 Extensions SetCwd module : B.4. Win32 Extensions SetFileAttributes method : 13.4. Modifying Permissions setting Registry values : 16.6. Setting Registry Values SetValue( ) : 16.6. Setting Registry Values SetValueEx( ) : 16.6. Setting Registry Values shebang line : 1.5. Basic Concepts shell, avoiding for new processes : 14.1. Using system and exec shift( ) : 3.4.4. The shift and unshift Functions ShortCut module : B.4. Win32 Extensions single-quoted strings : 2.3.1. Single-Quoted Strings skiing : 1.6. A Stroll Through Perl slash : 10.3. Using Pathnames and Filenames slices of array : 3.4.2. Array Element Access on literal lists : 3.4.2. Array Element Access variable interpolation in strings : 3.7. Variable Interpolation of Arrays Socket module : C. Networking Clients sockets : C. Networking Clients sort( ) 1.6.16. Maintaining a Last-Good-Guess Database 3.4.6. The sort Function controlling sort order of : 15.4. Advanced Sorting example of A.11. Chapter 12, Directory Access A.14. Chapter 15, Other Data Transformation example of : A.11. Chapter 12, Directory Access sort comparison routines : 15.4. Advanced Sorting using array lookups : 15.4. Advanced Sorting sorting
advanced : 15.4. Advanced Sorting example of numeric : 15.4. Advanced Sorting Sound module : B.4. Win32 Extensions space between array values when interpolated : 3.7. Variable Interpolation of Arrays in regular expressions : 7.3.1. Single-Character Patterns spaceship (<=>) operator : 15.4. Advanced Sorting example of : A.16. Chapter 17, Database Manipulation Spawn module : B.4. Win32 Extensions split( ) : 7.6.1. The split Function example of : 11.3. Invoking a Format spotted owls : 13.1. Removing a File sprintf( ) : 15.3. Formatting Data with sprintf( ) compared with pack( ) : 16.2. Packing and Unpacking Binary Data example of : 11.4.2. Numeric Fields Sprite : 2.3.2. Double-Quoted Strings square brackets ([ ]), in regular expressions : 7.3.1. Single-Character Patterns standard distribution, Perl : 1.3.2. Standard Perl Distribution standard error of command in backquotes : 14.2. Using Backquotes standard input example of using : 2.7. <STDIN> as a Scalar Value of command in backquotes : 14.2. Using Backquotes reading from : 6.1. Input from STDIN Standard Modules : B.2. Standard Modules standard output example of using : 2.8. Output with print stat( ) : 10.7. The stat Function statement block (see also blocks) 1.6.3. Adding Choices 4.1. Statement Blocks STDERR 1.6.10. Moving the Secret Word List into a Separate File 10.1. What Is a Filehandle?
STDIN 1.6.2. Asking Questions and Remembering the Result 1.6.10. Moving the Secret Word List into a Separate File 6.1. Input from STDIN 10.1. What Is a Filehandle? in array context : 3.6. <STDIN> as an Array example of : A.5. Chapter 6, Basic I/O example of 1.6.17. The Final Programs 6.1. Input from STDIN 9.1. The last Statement as scalar value : 2.7. <STDIN> as a Scalar Value as target of a match : 7.4.1. Selecting a Different Target (the =~ Operator) undef return value and : 2.9. The Undefined Value STDOUT 1.6.10. Moving the Secret Word List into a Separate File 10.1. What Is a Filehandle? string concatenation : 2.4.2. Operators for Strings string operators : 2.4.2. Operators for Strings strings 2.1. What Is Scalar Data? 2.3. Strings automatic conversion to numbers : 2.4.4. Conversion Between Numbers and Strings counting characters in : 15.5. Transliteration deleting characters from : 15.5. Transliteration length of : 2.3. Strings literal representation of : 2.3. Strings pathnames in : 2.3.2. Double-Quoted Strings removing last character : 2.6.3. The chop( ) and chomp( ) Functions sub keyword 1.6.9. Making It a Bit More Modular 8.1. Defining a User Function example of A.7. Chapter 8, Functions
1.6.17. The Final Programs subkeys : (see keys, registry) subroutine definitions example of : A.7. Chapter 8, Functions location of in file : 1.6.9. Making It a Bit More Modular location of in text : 8.1. Defining a User Function re-defining : 8.1. Defining a User Function subroutines 1.6.9. Making It a Bit More Modular 8.1. Defining a User Function arguments : 8.4. Arguments invoking : 8.2. Invoking a User Function lack of locals : 8.1. Defining a User Function nested invocation of : 8.2. Invoking a User Function return values of : 8.3. Return Values scope of variables : 8.1. Defining a User Function subscript reference, introduced : 1.6.5. More than One Secret Word subscripts array expressions : 3.4.2. Array Element Access with array elements : 3.4.2. Array Element Access substitute operator 1.6.8. Making It Fair for the Rest 7.2. Simple Uses of Regular Expressions 7.5. Substitutions substr( ) : 15.2. Extracting and Replacing a Substring example of : A.14. Chapter 15, Other Data Transformation variable as first argument : 15.2. Extracting and Replacing a Substring substrings, finding : 15.1. Finding a Substring subtraction, operator for : 2.4.1. Operators for Numbers subtrees, Registry : 16.4.1. The Registry Structure symlink( ) : 13. File and Directory Manipulation system( ) : 14.1. Using system and exec list of arguments to : 14.1. Using system and exec
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: T
-T operator : 10.6. The -x File Tests -t operator : 10.6. The -x File Tests Tab : 2.3.2. Double-Quoted Strings tar utility : 1.3.2. Standard Perl Distribution TCP, Perl and : C. Networking Clients technical support : 1.4. Support temperature : 4.7. Exercises template of format : 11.2. Defining a Format text editors, and updating databases : 17.5. Variable-Length ( Text) Databases text fields (in formats) : 11.4.1. Text Fields time manipulation of : 1.6.16. Maintaining a Last-Good-Guess Database UNIX internal format : 13.5. Modifying Timestamps time operator 1.6.17. The Final Programs 1.6.16. Maintaining a Last-Good-Guess Database 13.5. Modifying Timestamps timestamps, modifying : 13.5. Modifying Timestamps _TOP, as suffix for top-of-page format : 11.5. The Top-of-Page Format top-of-page format 11.5. The Top-of-Page Format 11.6.3. Changing the Top-of-Page Format Name example of : 1.6.14. Listing the Secret Words tr operator : 15.5. Transliteration example of 1.6.8. Making It Fair for the Rest 1.6.17. The Final Programs
translate operator, introduced : 1.6.8. Making It Fair for the Rest transliteration : 15.5. Transliteration true : 4.2. The if/unless Statement regular expressions : 7.2. Simple Uses of Regular Expressions
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: U
UNC path : 10.3. Using Pathnames and Filenames undef : 2.9. The Undefined Value array element access : 3.4.2. Array Element Access as default value for $^I : 17.5. Variable-Length ( Text) Databases as initial value of local variables : 8.5. Private Variables in Functions as return value from globbing : 12.2. Globbing as return value from pop( ) : 3.4.3. The push and pop Functions as return value from readdir( ) : 12.5. Reading a Directory Handle associative array elements : 5.2. Hash Variables resulting from split( ) : 7.6.1. The split Function STDIN and : 6.1. Input from STDIN to control dbmopen( ) : 17.2. Opening and Closing DBM Hashes when assigning lists : 3.4.1. Assignment underscore (_), in variable names : 2.5. Scalar Variables unless modifier : 9.5. Expression Modifiers unless statement : (see if statement) example of : 10.4. A Slight Diversion: die unlink( ) : 13.1. Removing a File example of : A.12. Chapter 13, File and Directory Manipulation unpack( ) : 16.2. Packing and Unpacking Binary Data example of 16.3. Getting Network Information 17.4. Fixed-Length Random-Access Databases return values from gethostbyname( ) : 16.3. Getting Network Information unshift( ) : 3.4.4. The shift and unshift Functions until modifier : 9.5. Expression Modifiers
until statement : (see while statement) uppercase for filehandles : 1.6.10. Moving the Secret Word List into a Separate File use statement 18.4. Passing Parameters via CGI 19.2. Creating Automation Objects user function : (see subroutines) utime( ) : 13.5. Modifying Timestamps
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: V
values( ) : 5.4.2. The values Function variable names for : 1.6.8. Making It Fair for the Rest variable interpolation : 2.6.4. Interpolation of Scalars into Strings array variables : 3.7. Variable Interpolation of Arrays double-quoted strings and : 2.3.2. Double-Quoted Strings globbing : 12.2. Globbing regular expressions : 7.4.4. Using Variable Interpolation the substitute operator : 7.5. Substitutions used with system( ) : 14.1. Using system and exec variable part of format : 11.1. What Is a Format? variables array : 3.3. Variables associative array : 5.2. Hash Variables default value of : 2.9. The Undefined Value predefined : D.6. Many, Many Predefined Variables scalar : 2.5. Scalar Variables subroutines and : 8.1. Defining a User Function Variant : 19.4. Variants VARIANT : 19.4. Variants Very Bad Programming Style, example of : 3.4.2. Array Element Access Visual Basic : 19.5.1. Translating Samples from Visual Basic von Neumann, John : Foreword to the First Edition of Learning Perl vowels, matching : 7.3.1. Single-Character Patterns
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: W
-w operator : 10.6. The -x File Tests \w, in regular expressions : 7.3.1. Single-Character Patterns Wall, Larry 1.4. Support 9.6. &&, ||, and ?: as Control Structures Foreword to the First Edition of Learning Perl Webget client (example) : C.2. A Webget Client while modifier : 9.5. Expression Modifiers while statement 1.6.4. Guessing the Secret Word 4.3. The while/until Statement example of A.3. Chapter 4, Control Structures 1.6.13. Many Secret Word Files in the Current Directory 1.6.9. Making It a Bit More Modular 5.4.1. The keys Function 5.4.3. The each Function 6.1. Input from STDIN last operator : 9.1. The last Statement next operator : 9.2. The next Statement redo operator : 9.3. The redo Statement whitespace : 1.5. Basic Concepts in formats : 11.2. Defining a Format in pack format string : 16.2. Packing and Unpacking Binary Data in Perl programs : 1.5. Basic Concepts in regular expressions : 7.3.1. Single-Character Patterns Win32 Extensions : B.4. Win32 Extensions
Win32::AbortSystemShutdown module : B.4. Win32 Extensions Win32::AdminMisc module : B.4. Win32 Extensions Win32::BuildNumber module : B.4. Win32 Extensions Win32::ChangeNotify module : B.4. Win32 Extensions Win32::Clipboard module : B.4. Win32 Extensions Win32::Console module : B.4. Win32 Extensions Win32::DomainName module : B.4. Win32 Extensions Win32::Error module : B.4. Win32 Extensions Win32::EventLog module : B.4. Win32 Extensions Win32::ExpandEnvironmentStrings module : B.4. Win32 Extensions Win32::File module B.4. Win32 Extensions 13.4. Modifying Permissions Win32::FileSecurity module B.4. Win32 Extensions 13.4. Modifying Permissions Win32::FormatMessage module : B.4. Win32 Extensions Win32::FsType function : 10.7. The stat Function Win32::FsType module : B.4. Win32 Extensions Win32::GetCwd function : 12.1. Moving Around the Directory Tree Win32::GetCwd module : B.4. Win32 Extensions Win32::GetLastError module : B.4. Win32 Extensions Win32::GetNextAvailDrive module : B.4. Win32 Extensions Win32::GetOSVersion module : B.4. Win32 Extensions Win32::GetShortPathName function : 10.3. Using Pathnames and Filenames Win32::GetShortPathName module : B.4. Win32 Extensions Win32::GetTickCount module : B.4. Win32 Extensions Win32::InitiateSystemShutdown module : B.4. Win32 Extensions Win32::Internet module : B.4. Win32 Extensions Win32::IPC module : B.4. Win32 Extensions Win32::IsWin95 module : B.4. Win32 Extensions Win32::IsWinNT module : B.4. Win32 Extensions Win32::LoginName function : 16.1. Getting User and Machine Information
Win32::LoginName module : B.4. Win32 Extensions Win32::LookupAccountName module : B.4. Win32 Extensions Win32::LookupAccountSID module : B.4. Win32 Extensions Win32::Mutex module : B.4. Win32 Extensions Win32::NetAdmin module B.4. Win32 Extensions 16.1. Getting User and Machine Information Win32::NetResource module B.4. Win32 Extensions 12.5. Reading a Directory Handle Win32::NodeName function : 16.1. Getting User and Machine Information Win32::NodeName module : B.4. Win32 Extensions Win32::ODBC module B.4. Win32 Extensions 17.6. Win32 Database Interfaces Win32::OLE module A.18. Chapter 19, OLE Automation B.4. Win32 Extensions 19.2. Creating Automation Objects Win32::Pipe module : B.4. Win32 Extensions Win32::Process : 14.5. Win32::Process Win32::Process module B.4. Win32 Extensions 14.5. Win32::Process Win32::Registry module A.15. Chapter 16, System Information B.4. Win32 Extensions Win32::Registry package 16.4. The Registry 16.4.1. The Registry Structure Win32::Semaphore module : B.4. Win32 Extensions Win32::Service module : B.4. Win32 Extensions Win32::SetCwd module : B.4. Win32 Extensions Win32::Shortcut module : B.4. Win32 Extensions
Win32::Sound module : B.4. Win32 Extensions Win32::Spawn module : B.4. Win32 Extensions Windows 95 vs. Windows NT : 1.3.3. Windows NT and Windows 95 Windows NT processes on : 14.5. Win32::Process Registry : 16.4. The Registry Windows 95 versus : 1.3.3. Windows NT and Windows 95 WinZip utility : 1.3.2. Standard Perl Distribution word boundary (regular expressions) 1.6.7. Handling Varying Input Formats 7.3.3. Anchoring Patterns word characters, in regular expressions : 7.3.1. Single-Character Patterns words, and filled fields in formats : 11.4.4. Filled Fields World Wide Web B.2.8. The World Wide Web 18. CGI Programming write( ) 1.6.14. Listing the Secret Words 1.6.17. The Final Programs 11.3. Invoking a Format
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: X
x operator (exmaple) : A.1. Chapter 2, Scalar Data -x operator : 10.6. The -x File Tests x, as string repetition operator : 2.4.2. Operators for Strings
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z
Index: Z
-z operator : 10.6. The -x File Tests
Search | Symbols | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Z