3

I'm trying to replace substrings delimited by characters in a string by the values of their matching bash variables in shell.

So far, I've tried this without any success:

varone="noob"
vartwo="trivial"
echo "my {varone} and {vartwo} question" | perl -pe 's|(.*){(\w+)}(.*)|${1}'$(echo "${'${2}'}")'${3}|g'

But I get:

bash: ${'${2}'}: bad substitution

Any idea on how to do this? Thanks in advance!

garys
  • 129
  • 9

4 Answers4

5

Your main problem here is that you need to use export in order for your variables to be seen in your subprocesses (like the perl process).

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question" | perl -pe '...'

You also need to know that shell variables are accessed inside a Perl program using the %ENV hash.

So your code can be simplified to:

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question" | perl -pe 's|\{(\w+)}|$ENV{$1}|g'

You might consider adding an option to check for unknown variables.

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question {varxxx}" | perl -pe 's|\{(\w+)}|$ENV{$1}//"UNKNOWN"|g'

But I'd recommend looking at a proper templating engine for this.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
5

Don't generate Perl code from the shell! It isn't easy.

Instead of generating code, pass the values to the script. This answer shows a couple of ways you can pass values to a Perl one-liner. Exporting the variables you want to interpolate is the simplest here.

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question" |
   perl -pe's/\{(\w+)\}/$ENV{$1}/g'

It also means you can interpolate other variables like PATH. If that's no good, you'll have to somehow check if the variable name is legal.

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question" |
   perl -pe's/\{(varone|vartwo)\}/$ENV{$1}/g'
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • That's it, I appreciate the perl solution without any external storage as well, thanks for pointing this out! – garys Sep 25 '19 at 15:01
1

Use export to access bash variables in Perl scripts:

Try this:

export varone="noob"
export vartwo="trivial"
echo "my {varone} and {vartwo} question" | perl -pe 's|(.*){(\w+)}(.*){(\w+)}(.*)|${1}${ENV{$2}}${3}${ENV{$4}}${5}|g'

Example

echo "my {varone} and {vartwo} question" | perl -pe 's|(.*){(\w+)}(.*){(\w+)}(.*)|${1}${ENV{$2}}${3}${ENV{$4}}${5}|g'
my noob and trivial question
sungtm
  • 547
  • 3
  • 12
0

Here is another approach:

echo "my {varone} and {vartwo} question" | \
     perl -wpE 'BEGIN{ %h = @ARGV;@ARGV=() } s|{(\w+)\}|$h{$1}|g' \
     "varone" "$varone" "vartwo" "$vartwo" 

Output:

my noob and trivial question
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174