DeveloperChris
DeveloperChris

Reputation: 3448

Using a Perl one-liner in a shell script

This has been frustrating me for hours now. I wrote a simple wrapper around a Perl one-liner to update the serials in some DNS zone files.

I feel compelled to add this:- Don't offer other ways to do this, OK? It's about why this won't work, not about how to achieve the result by other means.

Here is my simple script

#!/bin/bash
#loop through the supplied files updating the timestamp (serial)
SERIAL=`date +%Y%m%d%H%M`;
for name in $@
do
saCMD="'s/^(\W*)\d*.*;\W*serial/\${1}$SERIAL ; serial/g'"
#echo the command 
echo "perl -pi -e "$saCMD" $name"
#execute the command
`perl -pi -e $saCMD $name`
done
  

I have tried a multitude of different ways and it fails silently or with the message

Can't find string terminator "'" anywhere before EOF at -e line 1..

If I execute the echoed command it works faultlessly

I am on a Debian 7 system

Can anyone point out me to why this is not executing as I would expect it to?

EDIT:

Some example data

$TTL 300
domain.org. IN SOA     ns1.domain.com. admin.domain.org. (
                2014090914      ; serial, todays date+todays
                7200            ; refresh, seconds
                7200            ; retry, seconds
                2419200         ; expire, seconds
                3600 )          ; minimum, seconds        

The line of interest is 2014090914 ; serial, todays date+todays

Upvotes: 3

Views: 3317

Answers (2)

Jens
Jens

Reputation: 72786

There is at least a quoting issue. You make the single quotes a part of the saCMD="'s...'". They will not be removed by the shell but passed to perl, as you can see in the echo output.

In addition,

#execute the command
`perl -pi -e $saCMD $name`

has likely useless backticks. Or do you also want to run a command that's being output by the perl script? To debug shell scripts, place set -x at the beginning.

This works here:

#!/bin/bash
SERIAL=$(date +%Y%m%d%H%M)
for name in "$@"; do
  saCMD="s/^(\W*)\d*.*;\W*serial/\${1}$SERIAL ; serial/"
  perl -pi -e "$saCMD" "$name"
done

and turns your example data into

$TTL 300
domain.org. IN SOA     ns1.domain.com. admin.domain.org. (
                201508201330 ; serial, todays date+todays
                7200            ; refresh, seconds
                7200            ; retry, seconds
                2419200         ; expire, seconds
                3600 )          ; minimum, seconds

Upvotes: 2

choroba
choroba

Reputation: 242443

Proper quoting should help. You haven't shown the input data, so I can't test:

saCMD="s/^(\W*)\d*.*;\W*serial/\${1}$SERIAL ; serial/g" # No inner quotes.
perl -pi -e "$saCMD" "$name"

Also, /g seems pointless as the regex only matches at the beginning of the string (^).

Upvotes: 0

Related Questions