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
-imeans inplace editing, that is the output replaces the input file-nmeans go over the input file(s) line by line.-emeans, 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 withdate:. - Just like natural languages, perl also allows reversing the order of a conditional statement. So instead of
if (condition) { do_something }we can writedo_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