str='-e ENV_PASSWORD="foo" -e ENV_USER="bar-e sd" -e ENV_DB_NAME="mysite_staging" '
I need to retrieve the environment variable name in one variable and its value in another from the above string using a Bash script.
I tried the below code in Python which works in python3 but the same pattern is not working with grep
:
File: python_test.py
import re
str='-e ENV_PASSWORD="foo" -e ENV_USER="bar-e sd" -e ENV_DB_NAME="mysite_staging" '
re_pattern='-e\s (.*?)="(.*?)"'
rec_pattern = re.compile(re_pattern, re.VERBOSE)
res = rec_pattern.findall(str)
for x in res:
print(f'Name="{x[0]}" Value="{x[1]}"')
--------------
Output:
Name="ENV_PASSWORD" Value="foo"
Name="ENV_USER" Value="bar-e sd"
Name="ENV_DB_NAME" Value="mysite_staging"
File: bash_test.sh
#!/bin/bash
str='-e ENV_PASSWORD="foo" -e ENV_USER="bar -e sd" -e ENV_DB_NAME="mysite_staging" '
re_pattern='-e\s (.*?)="(.*?)"'
array=( $(grep -oP $re_pattern <<<$str) )
for i in ${array[@]}; do
echo $i;
done
CodePudding user response:
Storing these values in a string seems like an antipattern in the first place. See https://mywiki.wooledge.org/BashFAQ/050
Also, notice that Python and grep
(even with -P
) have distinct regex dialects and facilities.
Assuming that the format of your input is fairly rigid, I would simply use the built-in regex support in Bash.
#!/bin/bash
str='-e ENV_PASSWORD="foo" -e ENV_USER="bar -e sd" -e ENV_DB_NAME="mysite_staging" '
re_pattern='-e[[:space:]]*([^[:space:].=]*)="([^"]*)"'
while [[ $str =~ $re_pattern ]]; do
echo "variable: ${BASH_REMATCH[1]}"
echo "value: ${BASH_REMATCH[2]}"
str=${str#*${BASH_REMATCH[1]}=\"${BASH_REMATCH[2]}\"}
done
The pattern contains two parenthesized groups (other than that, it's just a reformulation of your Perl pattern to traditional ERE regex) where the first captures the variable, and the second captures the value; these capture groups are collected into the Bash built-in array BASH_REMATCH
from where we then pull them out.
This feels rather brittle (especially the parameter expansion at the end of the loop) but it works for your test case.
Demo: https://ideone.com/mY4HKI
As an aside, in your original attempt, you want "$(array[@]}"
and echo "$i"
with double quotes around the values; see also When to wrap quotes around a shell variable?
A better approach entirely would be to store the configuration in a standard machine-readable format like JSON or YAML, and take it from there.
CodePudding user response:
Use -E
option instead of -P
:
array=( $(grep -oE $re_pattern <<<$str) )
See live demo.