Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Remove one line from a file

  • TODO: use version control or -i.bak
  • TODO: mention that structured files such as YAML migh be better edited with a dedicated parser. What if the value associated with the key isn’t on the same line (as is common with arrays and hashes)?

I had a thousand YAML files that, for historical reasons, had a field called date:. At one point update the code processing these files and wanted to remove this date field from all the files.

For example the one that starts with date:

perl -i -n -e 'print $_ if $_ !~ /^date:/' *.yaml
  • -i means inplace editing, that is the output replaces the input file
  • -n means go over the input file(s) line by line.
  • -e means, here comes the code.

In the code

  • $_ represents the current line
  • /^date:/ is a regular expression where the two slashes are the delimeters. ^ means our regex has to match the beginning og the string. date: is just the string we match.
  • !~ is the regex not match operator. (=~ is the regex match operator)
  • So this expression $_ !~ /^date:/ checks if the current line starts with date:.
  • Just like natural languages, perl also allows reversing the order of a conditional statement. So instead of if (condition) { do_something } we can write do_something if condition.
  • We print the current line if id does not start with date:.

We can improve our code:

$_ is the default for print

We don’t need to explicitelly print the content of $_ if we just write print without telling perl what to print it will print the content of $_.

perl -i -n -e 'print if $_ !~ /^date:/' *.yaml

Use boolean not and the matching operator

Intead of the !~ “not match” operator we could use the match operator =~ and then use a boolean not:

perl -i -n -e 'print if not $_ =~ /^date:/' *.yaml

This in itself probbaly isn’t an improvement, but the matching operator also defaults to work on $_ if no parameter provided. Actually for this to work we even remove the match operator. If we have a regular expression without a matchin (or not-matching) operator then it defaults to work on the content of $_. Neat.

perl -i -n -e 'print if not /^date:/' *.yaml

Use unless

Another potential improvement to our code is using the unless keyword which is the same as if not.

perl -i -n -e 'print unless /^date:/' *.yaml