Found in /usr/share/perl/5.34/pod/perlfaq3.pod Can I write useful Perl programs on the command line? Yes. Read perlrun for more information. Some examples follow. (These assume standard Unix shell quoting rules.) # sum first and last fields perl -lane 'print $F[0] + $F[-1]' * # identify text files perl -le 'for(@ARGV) {print if -f && -T _}' * # remove (most) comments from C program perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c # make file a month younger than today, defeating reaper daemons perl -e '$X=24*60*60; utime(time(),time() + 30 * $X,@ARGV)' * # find first unused uid perl -le '$i++ while getpwuid($i); print $i' # display reasonable manpath echo $PATH | perl -nl -072 -e ' s![^/+]*$!man!&&-d&&!$s{$_}++&&push@m,$_;END{print"@m"}' OK, the last one was actually an Obfuscated Perl Contest entry. :-) Found in /usr/share/perl/5.34/pod/perlfaq4.pod How can I output Roman numerals? Get the <http://www.cpan.org/modules/by-module/Roman> module. How do I manipulate arrays of bits? Use "pack()" and "unpack()", or else "vec()" and the bitwise operations. For example, you don't have to store individual bits in an array (which would mean that you're wasting a lot of space). To convert an array of bits to a string, use "vec()" to set the right bits. This sets $vec to have bit N set only if $ints[N] was set: my @ints = (...); # array of bits, e.g. ( 1, 0, 0, 1, 1, 0 ... ) my $vec = ''; foreach( 0 .. $#ints ) { vec($vec,$_,1) = 1 if $ints[$_]; } The string $vec only takes up as many bits as it needs. For instance, if you had 16 entries in @ints, $vec only needs two bytes to store them (not counting the scalar variable overhead). Here's how, given a vector in $vec, you can get those bits into your @ints array: sub bitvec_to_list { my $vec = shift; my @ints; # Find null-byte density then select best algorithm if ($vec =~ tr/\0// / length $vec > 0.95) { use integer; my $i; # This method is faster with mostly null-bytes while($vec =~ /[^\0]/g ) { $i = -9 + 8 * pos $vec; push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); push @ints, $i if vec($vec, ++$i, 1); } } else { # This method is a fast general algorithm use integer; my $bits = unpack "b*", $vec; push @ints, 0 if $bits =~ s/^(\d)// && $1; push @ints, pos $bits while($bits =~ /1/g); } return \@ints; } This method gets faster the more sparse the bit vector is. (Courtesy of Tim Bunce and Winfried Koenig.) You can make the while loop a lot shorter with this suggestion from Benjamin Goldberg: while($vec =~ /[^\0]+/g ) { push @ints, grep vec($vec, $_, 1), $-[0] * 8 .. $+[0] * 8; } Or use the CPAN module Bit::Vector: my $vector = Bit::Vector->new($num_of_bits); $vector->Index_List_Store(@ints); my @ints = $vector->Index_List_Read(); Bit::Vector provides efficient methods for bit vector, sets of small integers and "big int" math. Here's a more extensive illustration using vec(): # vec demo my $vector = "\xff\x0f\xef\xfe"; print "Ilya's string \\xff\\x0f\\xef\\xfe represents the number ", unpack("N", $vector), "\n"; my $is_set = vec($vector, 23, 1); print "Its 23rd bit is ", $is_set ? "set" : "clear", ".\n"; pvec($vector); set_vec(1,1,1); set_vec(3,1,1); set_vec(23,1,1); set_vec(3,1,3); set_vec(3,2,3); set_vec(3,4,3); set_vec(3,4,7); set_vec(3,8,3); set_vec(3,8,7); set_vec(0,32,17); set_vec(1,32,17); sub set_vec { my ($offset, $width, $value) = @_; my $vector = ''; vec($vector, $offset, $width) = $value; print "offset=$offset width=$width value=$value\n"; pvec($vector); } sub pvec { my $vector = shift; my $bits = unpack("b*", $vector); my $i = 0; my $BASE = 8; print "vector length in bytes: ", length($vector), "\n"; @bytes = unpack("A8" x length($vector), $bits); print "bits are: @bytes\n\n"; } How can I know how many entries are in a hash? (contributed by brian d foy) This is very similar to "How do I process an entire hash?", also in perlfaq4, but a bit simpler in the common cases. You can use the "keys()" built-in function in scalar context to find out have many entries you have in a hash: my $key_count = keys %hash; # must be scalar context! If you want to find out how many entries have a defined value, that's a bit different. You have to check each value. A "grep" is handy: my $defined_value_count = grep { defined } values %hash; You can use that same structure to count the entries any way that you like. If you want the count of the keys with vowels in them, you just test for that instead: my $vowel_count = grep { /[aeiou]/ } keys %hash; The "grep" in scalar context returns the count. If you want the list of matching items, just use it in list context instead: my @defined_values = grep { defined } values %hash; The "keys()" function also resets the iterator, which means that you may see strange results if you use this between uses of other hash operators such as "each()". Found in /usr/share/perl/5.34/pod/perlfaq5.pod How can I manipulate fixed-record-length files? The most efficient way is using pack() and unpack(). This is faster than using substr() when taking many, many strings. It is slower for just a few. Here is a sample chunk of code to break up and put back together again some fixed-format input lines, in this case from the output of a normal, Berkeley-style ps: # sample input line: # 15158 p5 T 0:00 perl /home/tchrist/scripts/now-what my $PS_T = 'A6 A4 A7 A5 A*'; open my $ps, '-|', 'ps'; print scalar <$ps>; my @fields = qw( pid tt stat time command ); while (<$ps>) { my %process; @process{@fields} = unpack($PS_T, $_); for my $field ( @fields ) { print "$field: <$process{$field}>\n"; } print 'line=', pack($PS_T, @process{@fields} ), "\n"; } We've used a hash slice in order to easily handle the fields of each row. Storing the keys in an array makes it easy to operate on them as a group or loop over them with "for". It also avoids polluting the program with global variables and using symbolic references. Found in /usr/share/perl/5.34/pod/perlfaq6.pod How do I efficiently match many regular expressions at once? (contributed by brian d foy) You want to avoid compiling a regular expression every time you want to match it. In this example, perl must recompile the regular expression for every iteration of the "foreach" loop since $pattern can change: my @patterns = qw( fo+ ba[rz] ); LINE: while( my $line = <> ) { foreach my $pattern ( @patterns ) { if( $line =~ m/\b$pattern\b/i ) { print $line; next LINE; } } } The "qr//" operator compiles a regular expression, but doesn't apply it. When you use the pre-compiled version of the regex, perl does less work. In this example, I inserted a "map" to turn each pattern into its pre-compiled form. The rest of the script is the same, but faster: my @patterns = map { qr/\b$_\b/i } qw( fo+ ba[rz] ); LINE: while( my $line = <> ) { foreach my $pattern ( @patterns ) { if( $line =~ m/$pattern/ ) { print $line; next LINE; } } } In some cases, you may be able to make several patterns into a single regular expression. Beware of situations that require backtracking though. In this example, the regex is only compiled once because $regex doesn't change between iterations: my $regex = join '|', qw( fo+ ba[rz] ); while( my $line = <> ) { print if $line =~ m/\b(?:$regex)\b/i; } The function "list2re" in Data::Munge on CPAN can also be used to form a single regex that matches a list of literal strings (not regexes). For more details on regular expression efficiency, see *Mastering Regular Expressions* by Jeffrey Friedl. He explains how the regular expressions engine works and why some patterns are surprisingly inefficient. Once you understand how perl applies regular expressions, you can tune them for individual situations. Found in /usr/share/perl/5.34/pod/perlfaq8.pod How can I open a pipe both to and from a command? The IPC::Open2 module (part of the standard perl distribution) is an easy-to-use approach that internally uses "pipe()", "fork()", and "exec()" to do the job. Make sure you read the deadlock warnings in its documentation, though (see IPC::Open2). See "Bidirectional Communication with Another Process" in perlipc and "Bidirectional Communication with Yourself" in perlipc You may also use the IPC::Open3 module (part of the standard perl distribution), but be warned that it has a different order of arguments from IPC::Open2 (see IPC::Open3). Why can't I get the output of a command with system()? You're confusing the purpose of "system()" and backticks (``). "system()" runs a command and returns exit status information (as a 16 bit value: the low 7 bits are the signal the process died from, if any, and the high 8 bits are the actual exit value). Backticks (``) run a command and return what it sent to STDOUT. my $exit_status = system("mail-users"); my $output_string = `ls`; How can I capture STDERR from an external command? There are three basic ways of running external commands: system $cmd; # using system() my $output = `$cmd`; # using backticks (``) open (my $pipe_fh, "$cmd |"); # using open() With "system()", both STDOUT and STDERR will go the same place as the script's STDOUT and STDERR, unless the "system()" command redirects them. Backticks and "open()" read only the STDOUT of your command. You can also use the "open3()" function from IPC::Open3. Benjamin Goldberg provides some sample code: To capture a program's STDOUT, but discard its STDERR: use IPC::Open3; use File::Spec; my $in = ''; open(NULL, ">", File::Spec->devnull); my $pid = open3($in, \*PH, ">&NULL", "cmd"); while( <PH> ) { } waitpid($pid, 0); To capture a program's STDERR, but discard its STDOUT: use IPC::Open3; use File::Spec; my $in = ''; open(NULL, ">", File::Spec->devnull); my $pid = open3($in, ">&NULL", \*PH, "cmd"); while( <PH> ) { } waitpid($pid, 0); To capture a program's STDERR, and let its STDOUT go to our own STDERR: use IPC::Open3; my $in = ''; my $pid = open3($in, ">&STDERR", \*PH, "cmd"); while( <PH> ) { } waitpid($pid, 0); To read both a command's STDOUT and its STDERR separately, you can redirect them to temp files, let the command run, then read the temp files: use IPC::Open3; use IO::File; my $in = ''; local *CATCHOUT = IO::File->new_tmpfile; local *CATCHERR = IO::File->new_tmpfile; my $pid = open3($in, ">&CATCHOUT", ">&CATCHERR", "cmd"); waitpid($pid, 0); seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR; while( <CATCHOUT> ) {} while( <CATCHERR> ) {} But there's no real need for both to be tempfiles... the following should work just as well, without deadlocking: use IPC::Open3; my $in = ''; use IO::File; local *CATCHERR = IO::File->new_tmpfile; my $pid = open3($in, \*CATCHOUT, ">&CATCHERR", "cmd"); while( <CATCHOUT> ) {} waitpid($pid, 0); seek CATCHERR, 0, 0; while( <CATCHERR> ) {} And it'll be faster, too, since we can begin processing the program's stdout immediately, rather than waiting for the program to finish. With any of these, you can change file descriptors before the call: open(STDOUT, ">logfile"); system("ls"); or you can use Bourne shell file-descriptor redirection: $output = `$cmd 2>some_file`; open (PIPE, "cmd 2>some_file |"); You can also use file-descriptor redirection to make STDERR a duplicate of STDOUT: $output = `$cmd 2>&1`; open (PIPE, "cmd 2>&1 |"); Note that you *cannot* simply open STDERR to be a dup of STDOUT in your Perl program and avoid calling the shell to do the redirection. This doesn't work: open(STDERR, ">&STDOUT"); $alloutput = `cmd args`; # stderr still escapes This fails because the "open()" makes STDERR go to where STDOUT was going at the time of the "open()". The backticks then make STDOUT go to a string, but don't change STDERR (which still goes to the old STDOUT). Note that you *must* use Bourne shell (sh(1)) redirection syntax in backticks, not csh(1)! Details on why Perl's "system()" and backtick and pipe opens all use the Bourne shell are in the versus/csh.whynot article in the "Far More Than You Ever Wanted To Know" collection in <http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz> . To capture a command's STDERR and STDOUT together: $output = `cmd 2>&1`; # either with backticks $pid = open(PH, "cmd 2>&1 |"); # or with an open pipe while (<PH>) { } # plus a read To capture a command's STDOUT but discard its STDERR: $output = `cmd 2>/dev/null`; # either with backticks $pid = open(PH, "cmd 2>/dev/null |"); # or with an open pipe while (<PH>) { } # plus a read To capture a command's STDERR but discard its STDOUT: $output = `cmd 2>&1 1>/dev/null`; # either with backticks $pid = open(PH, "cmd 2>&1 1>/dev/null |"); # or with an open pipe while (<PH>) { } # plus a read To exchange a command's STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out our old STDERR: $output = `cmd 3>&1 1>&2 2>&3 3>&-`; # either with backticks $pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# or with an open pipe while (<PH>) { } # plus a read To read both a command's STDOUT and its STDERR separately, it's easiest to redirect them separately to files, and then read from those files when the program is done: system("program args 1>program.stdout 2>program.stderr"); Ordering is important in all these examples. That's because the shell processes file descriptor redirections in strictly left to right order. system("prog args 1>tmpfile 2>&1"); system("prog args 2>&1 1>tmpfile"); The first command sends both standard out and standard error to the temporary file. The second command sends only the old standard output there, and the old standard error shows up on the old standard out. Is there a way to hide perl's command line from programs such as "ps"? First of all note that if you're doing this for security reasons (to avoid people seeing passwords, for example) then you should rewrite your program so that critical information is never given as an argument. Hiding the arguments won't make your program completely secure. To actually alter the visible command line, you can assign to the variable $0 as documented in perlvar. This won't work on all operating systems, though. Daemon programs like sendmail place their state there, as in: $0 = "orcus [accepting connections]";
Generated by phpMan v2.3-6-g99186f7 Author: Che Dong Under GNU General Public License
2026-06-03 02:46 @216.73.216.151
CrawledBy Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)