7 substenv - Substitute environment variables in parameters and run the resulting command
11 substenv [I<OPTIONS>] [--] I<COMMAND> [I<ARGS>]
15 Replace all occurrances of C<$NAME> in I<COMMAND> and I<ARGS> to the I<NAME> environment
16 variable's value, whatever I<NAME> would be, then run I<COMMAND> I<ARGS>.
17 Support C<${NAME}> curly bracket notation too.
25 Replace all occurrances of any C<$NAME> (and C<${NAME}>) substring
26 (for details see S<LIMITATIONS>).
27 This is the default behaviur, unless B<-e> is given.
29 =item -e, --environment I<NAME>
31 Replace the occurrances of I<NAME> environment variable.
32 May be specified more than once.
33 If B<-a> option is NOT given, ONLY these I<NAME>s are replaced.
35 =item -k, --keep-undefined
37 Do not replace variables which are not defined (ie. not in the environment),
39 By default they are replaced with the empty string.
41 =item --dryrun, --dry-run
43 Do not run I<COMMAND>, just print what would be executed.
49 This function call, in C, runs substenv(1),
50 note, there is no dollar-interpolation in C.
52 execve("substenv", ["substenv", "ls", "$HOME/.config"])
54 Then substenv issues this system call:
56 execve("ls", ["ls", "/home/jdoe/.config"])
60 In "substitute all" mode (without B<-e> flag) it replaces only names
61 with uppercase letters, digits, and underscore (C<[A-Z0-9_]+>),
62 as env vars usually contain only these chars.
63 However it still replaces variables with lowercase letters in C<${NAME}> notation,
64 and specific variable(s) given in B<-e> option(s).
66 Does not honour escaped dollar marks, ie. C<\$>.
70 Does not support full shell-like variable interpolation.
71 Use a real shell for it.
75 Sometimes you don't want a shell to be in the picture when composing commands,
76 yet need to weave some environment variable into it.
80 envsubst(1) from gettext-base package
86 use Getopt
::Long qw
/:config no_ignore_case no_bundling no_getopt_compat no_auto_abbrev require_order/;
88 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
97 'a|all!' => \
$OptAlwaysAll,
98 'e|env|environ|environment=s@' => \
@subst_env_only,
99 'k|keep-undefined!' => \
$OptKeepUndef,
100 'dry-run|dryrun!' => \
$OptDryRun,
101 'help' => sub { pod2usage
(-exitval
=>0, -verbose
=>99); },
102 '<>' => sub { unshift @ARGV, @_[0]; die '!FINISH'; },
103 ) or pod2usage
(-exitval
=>2, -verbose
=>99);
106 $bare_env_name_regex = '[A-Z_][A-Z0-9_]*';
107 $bracketed_env_name_regex = '[^}]+';
110 my $specific_env_names_regex = join '|', map { quotemeta } @subst_env_only;
113 $bare_env_name_regex = $specific_env_names_regex . '|' . $bare_env_name_regex;
114 $bracketed_env_name_regex = $specific_env_names_regex . '|' . $bracketed_env_name_regex;
118 $bare_env_name_regex = $bracketed_env_name_regex = $specific_env_names_regex;
127 my $whole_substring = shift;
128 if(not $OptKeepUndef or exists $ENV{$varname}) {
129 return $ENV{$varname};
132 return $whole_substring;
138 $arg =~ s/\$(\{(?<NAME>$bracketed_env_name_regex)\}|(?<NAME>$bare_env_name_regex))/subst_env($+{'NAME'}, $&)/eg;
145 warn Dumper \
@run_cmd;
149 exec {$run_cmd[0]} @run_cmd;
150 ($errno, $errstr) = (int $!, $!);
151 warn "$0: ${run_cmd[0]}: $errstr\n";