in reply to Re^2: backticks execution "inside" variable (string)
in thread backticks execution "inside" variable (string)

"... I didn't know [3..5] construct, thank you for that specifically, enriched me by that knowledge."

You're welcome. I see ++haukex has commented on that construct — I've nothing further to add unless you have questions about it.

"... but I was curious, if there is something yet simpler, what will replace all occurences ..."

Personally, I still think your approach to this is questionable; I'll discuss that in more detail further down. One standard way to do multiple replacements is with a substitution using the 'g' modifier (s///g). So, this would achieve what you're questionably asking for:

$ perl -E ' my $x = $ARGV[0] =~ s/(`[^`]+`)/$1/eegr =~ s/\R//gr; say $x; ' 'DMY_`date +%d%m%Y`_MY_`date +%m%Y`_Y_`date +%Y`.log' DMY_21122019_MY_122019_Y_2019.log

Note that say and \R became available in v5.10 and the 'r' modifier in v5.14. Depending on your Perl version, you might need something like:

$ perl -e ' my $x = $ARGV[0]; $x =~ s/(`[^`]+`)/chomp(my $y = eval $1); $y/eg; print "$x\n"; ' 'DMY_`date +%d%m%Y`_MY_`date +%m%Y`_Y_`date +%Y`.log' DMY_21122019_MY_122019_Y_2019.log

Important: Please be very aware that I am not recommending this approach; I'm merely advising of options.

The security issues have already been pointed out. In my opinion, it's just far too easy for some bad command to become embedded in your filenames. This could be accidental — a simple typo by your good self — or malicious; however, that's completely immaterial. The fact that it could happen should be sufficient to steer you away from this course of action.

I would suggest you create a module which does all the work for you and contains tokens representing only those commands that you choose to allow. I would also pick something other than backticks to delimit the command tokens; in the following, I've used tildes as an example alternative but pick whatever you like (it doesn't need to be a single character).

Here's a rough example of what that module might look like. I've continued using localtime purely for consistency with previous example code I provided; I see lots of alternative suggestions in this thread — pick whatever you want.

package Pm_11110263_FilenameGen; use strict; use warnings; use Exporter 'import'; our @EXPORT_OK = qw{gen_filename}; my %dispatch = ( 'DATE DMY' => sub { my ($d, $m, $y) = (localtime)[3..5]; return join '', $d, $m+1, $y+1900; }, 'DATE MY' => sub { my ($m, $y) = (localtime)[4,5]; return join '', $m+1, $y+1900; }, 'DATE Y' => sub { return (localtime)[5] + 1900; }, ); sub _perform_substitution { my ($token) = @_; die "FATAL! '$token' is invalid" unless exists $dispatch{$token}; return $dispatch{$token}->(); } sub gen_filename { my ($template) = @_; $template =~ s/~([^~]+)~/_perform_substitution($1)/eg; return $template; } 1;

Now you only need to use that module and call gen_filename():

$ perl -E ' use lib "."; use Pm_11110263_FilenameGen "gen_filename"; say gen_filename($ARGV[0]); ' 'daily_~DATE DMY~_monthly_~DATE MY~_yearly_~DATE Y~.log' daily_21122019_monthly_122019_yearly_2019.log

The 'use lib ".";' is only there because, for demo purposes, I put "Pm_11110263_FilenameGen.pm" in the current working directory. So, after a proper installation of the module, you'd only need two lines of code.

And if someone (accidentally or maliciously) tried something bad, no harm would be done.

$ perl -E ' use lib "."; use Pm_11110263_FilenameGen "gen_filename"; say gen_filename($ARGV[0]); ' 'daily_~DATE DMY~_monthly_~DATE MY~_yearly_~DATE Y~_BAD_~RM ROOT~.lo +g' FATAL! 'RM ROOT' is invalid at Pm_11110263_FilenameGen.pm line 26.

— Ken

Replies are listed 'Best First'.
A reply falls below the community's threshold of quality. You may see it by logging in.