Home > OS >  how to retrieve environment name and its value from the string using regex
how to retrieve environment name and its value from the string using regex

Time:09-26

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.

  • Related