0

Is it possible to invoke a program such as Perl from a Bash script to perform a regex with named capture groups and export the results as variables back to the parent shell?

For example:

#!/bin/bash

input="a small box"
regex="a (?P<size>\w+) box"

perl -e "
my \$str = \"$input\";

if ( \$str =~ /$regex/ ) {
   # Do a thing...
}
"

# Illustrative purposes only
echo $size

The expected output would be small.

This doesn't have to be done with Perl specifically. I just want to know if this can be done and demonstrated.

I have a few thousand files to parse and need to build a very large and complex regular expression to handle their contents. While this can be done with other tools such as pcregrep or =~ with numbered capture groups, I would prefer to use named capture groups for clarity.

I don't feel that I need to use anything other than Bash except for the heavy lifting of this complex regular expression. Is there a way to easily drop into another language to take advantage of named capture groups and export the result back to the parent environment?

Zhro
  • 2,546
  • 2
  • 29
  • 39
  • This regex capture looks trivial. How complex are your other expressions? Are you planning to export them all in one script? Does the input for the regex match come from a file? Provide an actual example of your samples to match – Inian Apr 02 '19 at 06:00
  • The input comes from a single file but the file itself is very large and the expression will also be fairly complex. The example provided is just for illustration. – Zhro Apr 02 '19 at 06:01
  • So what suggestion are you looking for now? Doing the regex match or setting the variables to parent shell? There is nothing to work with here – Inian Apr 02 '19 at 06:03
  • Setting the variables to the parent shell. If `eval` is offered for an answer then I would expect it to also account for special cases such as escaping and assignments which include newlines. – Zhro Apr 02 '19 at 06:05
  • Does the answers here help - https://stackoverflow.com/q/16618071/5291015 ? IMHO, if so this question is just a duplicate of that – Inian Apr 02 '19 at 06:06

1 Answers1

1

There is no way to export a variable from a subprocess to a parent process.

The closest to that would be child process giving output in a way that a bash shell can evaluate. E.g. if your perl program would output

export LEGS=3
export ANIMAL='Lame boar'

then you can invoke it from bash like this:

eval $(perl animal.pl)

and those variables would be inserted into your environment:

echo "$ANIMAL has $LEGS legs."

EDIT: With Ruby, assuming input and regex are defined,

eval $(ruby -r shellwords -e "
if (match = ENV['input'].match(ENV['regex']))
  match.names.each do |name|
    puts %{export #{name}=#{Shellwords::shellescape(match[name])}}
  end
end
")
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • I was hoping to avoid this. Escaping all assignments provided to `eval` will be troublesome. – Zhro Apr 02 '19 at 06:03
  • Dunno about Perl, but in Ruby, it's as easy as `require "shellescape"; puts "ANIMAL=#{Shellwords::shellescape(animal)}"` – Amadan Apr 02 '19 at 06:07
  • I don't know anything about Ruby but I would appreciate it if you would offer an answer on how this would be done as a reference. – Zhro Apr 02 '19 at 06:09
  • I can't until you specify the question more concretely. There is no escaping necessary for the word `small` in your question; you talk about large files but specify a string; etc. You need to make your example problem similar to your real problem. (Also, Ruby doesn't do PCRE, though its own regexp library Onigmo is almost as powerful.) – Amadan Apr 02 '19 at 06:11
  • In Perl, you have String::ShellQuote's `shell_quote` – ikegami May 17 '21 at 14:32