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
  • 117
  • 6

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
  • 65,668
  • 3
  • 47
  • 91
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
  • 343,984
  • 15
  • 249
  • 495
  • 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
  • 557
  • 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
  • 36,323
  • 18
  • 71
  • 152