In this chapter, we’ll look at various one-liners for numbering lines and words, and you’ll get to know the $. special variable. You’ll also learn about Perl golfing, a “sport” that involves writing the shortest Perl program to get a task done.
3.1 Number all lines in a file
perl -pe '$_ = "$. $_"' file 标上行号
同
perl -ne 'print "$. $_"' file
3.2 Number only non-empty lines in a file
perl -pe '$_ = ++$x." $_" if /./'
同
perl -pe '$_ = ++$x." $_" if /\S/' 跳过空行标号
3.3 Number and print only non-empty lines in a file
(drop empty lines)
perl -ne 'print ++$x." $_" if /./' file
3.4 Number all lines but print line numbers only for
non-empty lines
perl -pe '$_ = "$. $_" if /./'
3.5 Number only lines that match a pattern;
print others unmodified
perl -pe '$_ = ++$x." $_" if /record/'
3.6 Number and print only lines that match a pattern
perl -ne 'print ++$x." $_" if /regex/'
3.7 Number all lines but print line numbers only for
lines that match a pattern
perl -pe '$_ = "$. $_" if /regex/'
3.8 Number all lines in a file using a custom format
perl -ne 'printf "%-5d %s", $., $_'
3.9 Print the total number of lines in a file(emulate wc -l)
perl -lne 'END { print $. }'
You can do the same thing with this one-liner:
perl -le 'print $n = () = <>'
What’s really happening here is the = operator is right-associative, meaning the = on the right is done first and the = on the left is done second:
perl -le 'print $n = (() = <>)'
You can also drop the variable $n from this one-liner and force the
scalar context through the scalar operator:
perl -le 'print scalar(() = <>)'
And now for a more obvious version:
perl -le 'print scalar(@foo = <>)'
And here’s another way to do it:
perl -ne '}{print $.'
3.10 Print the number of non-empty lines in a file
perl -le 'print scalar(grep { /./ } <>)'
Some Perl programmers like to create the shortest Perl program that does some particular task—an exercise called Perl golfing. A golfer’s version of this one-liner would replace scalar() with ~~ (double bitwise
negate) and drop the spaces, shortening it like this:
perl -le 'print ~~grep{/./}<>'
3.11 Print the number of empty lines in a file
perl -lne '$x++ if /^$/; END { print $x+0 }'
An alternative to $x+0 is the int operator:
perl -lne '$x++ if /^$/; END { print int $x }'
You could also modify the previous one-liner by doing this:
perl -le 'print scalar(grep { /^$/ } <>)'
Or write it with ~~:
perl -le 'print ~~grep{ /^$/ } <>'
The ~~ does bitwise negation twice, which makes grep execute in the scalar context and return the number of empty lines.
3.12 Print the number of lines in a file that match a
pattern (emulate grep -c)
perl -lne '$x++ if /regex/; END { print $x+0 }'
3.13 Number words across all lines
perl -pe 's/(\w+)/++$i.".$1"/ge'
This one-liner uses the /e flag, which makes Perl evaluate the replace part of the s/regex/replace/ expression as code!
3.14 Number words on each individual line
perl -pe '$i=0; s/(\w+)/++$i.".$1"/ge'
3.15 Replace all words with their numeric positions
perl -pe 's/(\w+)/++$i/ge'