Perl: A Better Cross-Platform CLI Tool Across Unix Systems
1. Context
On Linux systems, 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 pipeline. 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 couldn’t force it to be the default because doing so might break some scripts on the machine that assume 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 on others due to version differences.
2. Perl
I went looking online for a solution and saw perl
being recommended multiple times.
I never used Perl but knew 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 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 tends to be more readable for some one-liners.