0

Within a larger bash script I use a line with a perl command to substitute a time stamp in a text file with the current date and time. I use the following the lines:

perlcmd="perl -i -pe 's/2005-03-31T19:13:30/$(date +"%Y-%m-%dT%H:%M:%S")/' ./file.txt"
echo $perlcmd
$perlcmd

The echo command shows me that the perl command is okay, its output is:

perl -i -pe 's/2005-03-31T19:13:30/2017-12-21T11:33:44/' ./file.txt

The time stamp, however, is not substituted. When I paste the echoed line to the command line it is executed properly and the time stamp is substituted. How to I have to change the code in the bash script to make it work?

user7417
  • 1,531
  • 3
  • 15
  • 20
  • Don't put your command in a variable http://mywiki.wooledge.org/BashFAQ/050 (and if you do anyway, [quote it properly](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable)). – tripleee Dec 21 '17 at 11:19

1 Answers1

0

because the single quotes in prelcmd variable are interpreted literally and not syntacticaly (because of shell command line processing not specific to bash but posix shell quoting is before parameter expansion), easiest is to use an array instead :

perlcmd=(perl -i -pe 's/2005-03-31T19:13:30/'"$(date +"%Y-%m-%dT%H:%M:%S")"'/' ./file.txt)
echo "${perlcmd[*]}"
"${perlcmd[@]}"

another solution is to reinterpret perlcmd using eval

perlcmd="perl -i -pe 's/2005-03-31T19:13:30/$(date +"%Y-%m-%dT%H:%M:%S")/' ./file.txt"
echo "$perlcmd"
eval "$perlcmd"

Following comment: if $NewTitle may contain any character including /, perl code will break or code can be injected. To avoid this problem data can be passed by parameter or by environment, also if data can be used in a regex pattern and can contain meta character it can be quoted \Q .. \E:

by parameter:

perl -i -pe 'BEGIN{$old=shift@ARGV;$new=shift@ARGV}s/\Q$old\E/$new/' "$old_title" "$new_title" ./file.txt

by environment:

old_title=$old_title new_title=$new_title perl -i -pe 's/\Q$ENV{old_title}\E/$ENV{new_title}/' ./file.txt
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36
  • Great! And if I want to substitute a string by a string saved in a variable? Let's say the variable NewTitle contains the desired new string. perlcmd=(perl -i -pe 's/OldTitle/$NewTitle/' ./file.txt) does not work, so what other modification is necessary? – user7417 Dec 21 '17 at 11:29
  • because of single quote preventing parameter expansion , just close single quotes open double then close double open single 's/OldTitle/'"$NewTitle"'/', but code generation, is tricky to maintain and may be not safe regarding code injection – Nahuel Fouilleul Dec 21 '17 at 11:32