Penguin
Blame: PerlOneLiners
EditPageHistoryDiffInfoLikePages
Annotated edit history of PerlOneLiners version 31, including all changes. View license author blame.
Rev Author # Line
23 AristotlePagaltzis 1 Many oneliners rely on the magic of [Perl]'s <tt>-i</tt> switch, which means when files supplied on the commandline are opened they are edited in place, and if an extension was passed, a backup copy with that extension will be made. <tt>-e</tt> specifies the [Perl] code to run. See perlrun(1) for any other switches used here - in particular, <tt>-n</tt> and <tt>-p</tt> make powerful allies for <tt>-i</tt>.
10 GreigMcGill 2
3 The unsurpassed power of [Perl]'s RegularExpression flavour contributes a great deal to the usefulness of nearly every oneliner, so you will also want to read the perlretut(1) and perlre(1) manpages to learn about it.
20 CraigBox 4
5 !! Perl pie
6
23 AristotlePagaltzis 7 <verbatim>
8 perl -pi -e 's/foo/bar/' file
9 </verbatim>
20 CraigBox 10
23 AristotlePagaltzis 11 Does an inplace [SED] on the file. [GNU] sed(1) v4 also supports this with <tt>-i</tt> and will probably be quicker if you only need a simple query and replacement. However, [Perl]'s [RegularExpression]s are more powerful and easier on the hands than the [POSIX] variety offered by [SED]. With [GNU] sed(1), you can use the <tt>-r</tt> switch to get an extended RegularExpression syntax which also requires fewer backslashes than the [POSIX] flavour.
10 GreigMcGill 12
13 !! Removing empty lines from a file
14
23 AristotlePagaltzis 15 <verbatim>
16 perl -ni.bak -e'/\S/ && print' file1 file2
17 </verbatim>
10 GreigMcGill 18
16 AristotlePagaltzis 19 In [Shell]:
20
23 AristotlePagaltzis 21 <verbatim>
22 for FILE in file1 file2 ; do mv "$F"{,.bak} ; grep '[^ ]' "$F.bak" > "$F" ; done
23 </verbatim>
10 GreigMcGill 24
25 !! Collapse consecutive blank lines to a single one
26
23 AristotlePagaltzis 27 <verbatim>
28 perl -00 -pi.bak -e1 file1 file2
29 </verbatim>
10 GreigMcGill 30
23 AristotlePagaltzis 31 Note the use of <tt>1</tt> as a no-op piece of Perl code. In this case, the <tt>-00</tt> and <tt>-p</tt> switches already do all the work, so only a dummy needs to be supplied.
10 GreigMcGill 32
33 !! Binary dump of a string
34
23 AristotlePagaltzis 35 <verbatim>
36 perl -e 'printf "%08b\n", $_ for unpack "C*", shift' 'My String'
37 </verbatim>
10 GreigMcGill 38
39 !! Replace literal "\n" and "\t" in a file with newlines and tabs
40
23 AristotlePagaltzis 41 <verbatim>
42 perl -pe 's!\\n!\n!g; s!\\t!\t!g' $file
43 </verbatim>
12 AristotlePagaltzis 44
23 AristotlePagaltzis 45 Note that you can use any punctuation as the separator in an <tt>s///</tt> command, and if you have backslashes or even need literal slashes in your pattern then doing this can increase clarity.
26 JohnMcPherson 46
47 !! Convert data from rows to columns
27 AristotlePagaltzis 48 This assumes that each of the input rows is exactly the same length (in terms of number of items), and assumes they are separated by spaces. This is useful if you have data in tabular form, but need it to be in columns instead (eg. you want to use it as input to GnuPlot).
26 JohnMcPherson 49
28 JohnMcPherson 50 <verbatim>
51 perl -e '@rows=();
52 while ($l=<>) {@line=split(/ \s+/,$l); push @rows, [@line ]}
53 for $i (0 .. @{$rows[0]}) {
54 for $row (@rows) {print $row->[$i] . "\t"}
55 print "\n"
56 }'
57 </verbatim>
29 AristotlePagaltzis 58
59 Alternatively you can let [Perl] do the drudgework work for you. In the following, <tt>-n</tt> implies the <tt>while(<>){}</tt> loop and the <tt>-a -F''regex''</tt> imply the <tt>split</tt> (the result is stored in the predefined <tt>@F</tt> array). Anyone who is at all familiar with [AWK] should follow along easily.
60
26 JohnMcPherson 61 <verbatim>
29 AristotlePagaltzis 62 perl -aF'\s+' -ne'push @rows, [ @F ]; END {
27 AristotlePagaltzis 63 for $i ( 0 .. $#{ $rows[0] } ) {
64 for $cols ( @rows ) { print $cols->[ $i ] . "\t" }
65 print "\n"
66 }
67 }'
26 JohnMcPherson 68 </verbatim>
27 AristotlePagaltzis 69
30 AristotlePagaltzis 70 Both of these will read whitespace-separated tabular data from stdin(3) or from the files passed, and will write to tab-separated tabular data to stdout(3).
24 CraigBox 71
13 JohnMcPherson 72 !! List all currently running processes
73
14 AristotlePagaltzis 74 This is useful if you suspect that ps(1) is not reliable, whether due to a RootKit or some other cause. It prints the process ID and command line of every running process on the system (except some "special" kernel processes that lie about/don't have command lines).
13 JohnMcPherson 75
23 AristotlePagaltzis 76 <verbatim>
77 perl -0777 -pe 'BEGIN { chdir "/proc"; @ARGV = sort { $a <=> $b } glob("*/cmdline") }
78 $ARGV =~ m!^(\d+)/!; print "$1\t"; s/\0/ /g; $_ .= "\n";'
79 </verbatim>
14 AristotlePagaltzis 80
23 AristotlePagaltzis 81 It runs an implicit loop over the <tt>/proc/*/cmdline</tt> files, by priming <tt>@ARGV</tt> with a list of files sorted numerically (which needs to be done explicitly using <tt><=></tt> -- the default sort is [ASCII]betical) and then employing the <tt>-p</tt> switch. <tt>-0777</tt> forces files to be slurped wholesale. Per file, the digits that lead the filename are printed, followed by a tab. Since a null separates the arguments in these files, all of them are replaced by spaces to make the output printable. Finally, a newline is appended. The print call implicit in the <tt>-p</tt> switch then takes care of outputting the massaged command line.
15 AristotlePagaltzis 82
83
84 !! List all currently running processes, but nicer
85
86 See above for what this does. The ''how'' is different, though.
87
23 AristotlePagaltzis 88 <verbatim>
89 perl -MFile::Slurp -0le 'for(sort { $a <=> $b } grep !/\D/, read_dir "/proc")
90 { @ARGV = "/proc/$_/cmdline"; printf " %6g %s\n", $_, join(" ", <>); }'
91 </verbatim>
15 AristotlePagaltzis 92
23 AristotlePagaltzis 93 This time the loop is explicit. Again, there are two parts to the program -- selecting files and doing [I/O] on them.
15 AristotlePagaltzis 94
23 AristotlePagaltzis 95 To read the directory, a convenience function is pulled in from the File::Slurp module, loaded using the <tt>-M</tt> switch. The module has been part of the core distribution since Perl 5.8.0. Reading a directory manually is straightforward but the code would be longer and clumsier.
15 AristotlePagaltzis 96
23 AristotlePagaltzis 97 Selecting the files is pretty simple, if a little obtuse: it's done by reading the contents of <tt>/proc</tt>, then using <tt>grep !/D/</tt> to reject any entries that contain non-digit characters from the list. The results are then sorted numerically, which needs to be done explicitly using the <tt><=></tt> operator because the default sort is [ASCII]betical. Each entry is then interpolated into a full path and stuck into <tt>@ARGV</tt> one by one, from where the <tt><></tt> "diamond operator" will pick it up, auto-open it and read it for us, even autoreporting any errors in a nicely verbose format.
15 AristotlePagaltzis 98
23 AristotlePagaltzis 99 Producing human-readable output is a little more involved, using switches to abbreviate a bit of magic. The <tt>-0</tt> switch sets the <tt>$/</tt> variable: here, because the switch is not followed by a digit, it sets the variable to a null character. This means that null characters will be regarded as line separators on input. The <tt>-l</tt> switch has two effects, of which only one is relevant to us: it automatically removes line terminators from lines read using the diamond operator. (The other is to set the <tt>$\</tt> variable, which we aren't interested in or affected by.)
15 AristotlePagaltzis 100
23 AristotlePagaltzis 101 Note that the <tt>-0</tt> and <tt>-l</tt> switches are order sensitive both in syntax and semantics. We order them for syntax here, because they can both accept an octal number as input, but we don't to pass one to either of them (particularly, <tt>-0</tt> will be mistaken for a digit parameter to <tt>-l</tt> if we turn them around).
15 AristotlePagaltzis 102
23 AristotlePagaltzis 103 Together, these switches effectively mean that we get null terminated lines from files, with the nulls removed on input. So we get the command line arguments listed in a <tt>/proc/*/cmdline</tt> file as nice list of separate strings. And because <tt>join()</tt> expects a list, <tt><></tt> returns all "lines" (ie command line arguments) at once, which <tt>join()</tt> then dutifully puts together with spaces between.
15 AristotlePagaltzis 104
105 The printf(3) is straightforward.

PHP Warning

lib/blame.php:177: Warning: Invalid argument supplied for foreach() (...repeated 4 times)