Perl: a better cross-platform cli tool across Unix systems
1. Context
On a Linux system, grep
, sed
and awk
are old and ubiquitous tools.
They are often considered standard, and relied upon by users.
However, I recently encountered a case where sed
does not run the same
across Unix systems.
1.1. Problem
At work, as part of a tool running on the local machine of the developer, and in the CI/CD pipeline, I needed to remove some lines from a file before processing it further.
I reached for sed
, and tested the command successfully on the CI/CD pipeline:
sed -i -e '/xxx/d' file.txt
However, while testing on my Mac laptop, it couldn’t run, unless I provided an
empty argument to -i
:
sed -i '' -e '/xxx/d' file.txt
But, this would no longer run in the CI/CD.
It turns out that the GNU sed
, and the Mac OS sed
do not behave exactly the same,
in many different ways.
The sed
implementation on Mac comes from a BSD, and so BSD systems are also affected
(depending on the version of the system).
1.2. Other issues
At first, I thought about installing GNU sed
on Mac, but I cannot force it to
be the default, because doing so may break some scripts on the machine that assume
that sed
is the default one.
This also reminded me of a time when I met some issues with GNU grep
sometimes
not having the -P
option for better regular expression support on some systems
in the company, while present in others (due to versions differences).
2. Perl
I went looking online for a solution, and I saw perl
being recommended multiple
time.
I never used Perl, but I know it was ubiquitous, because it was once very
popular for web applications. It also brought powerful regular expressions that
we take for granted in other systems (like that -P
option of grep
meaning Perl
).
For one liners, I thought I could give it a try (Perl being pre-installed on Mac OS, and Perl ensuring a very strong compatibility from one version to another).
2.1. grep, sed and awk: Perl Equivalents
# Perl
perl -ne 'print if /pattern/' file.txt
# Linux
grep -P 'pattern' file.txt
# Perl
perl -ne 'print if not /pattern/' file.txt
# Linux
grep -P -v 'pattern' file.txt
# Perl
perl -i -ne 'print if not /pattern/' file.txt
# Linux
sed -i -e '/pattern/d' file.txt
# Perl
perl -i -ne 's/pattern/replacement/g; print' file.txt
# Linux
sed -i -e 's/pattern/replacement/g' file.txt
# Perl
ps aux | perl -a -ne 'print $F[1],"\n"'
# Linux
ps aux | awk '{ print $2 }'
# Perl
perl -ne '/(pattern)/ and print $1, "\n"' file.txt
# Linux
grep -P -o 'pattern' file.txt
# Perl
ps aux | perl -ne 'END { print $. }'
# Linux
ps aux | wc -l
3. Conclusion
After a short learning curve, it turns out that Perl works the same across systems, and tend to be more readable for some one-liners.