str='-e ENV_PASSWORD="foo" -e ENV_USER="bar-e sd" -e ENV_DB_NAME="mysite_staging" '
我需要使用Bash脚本从上面的字符串中检索一个变量中的环境变量名和另一个变量的值。
我在Python中尝试了以下代码,该代码适用于python3,但相同的模式不适用于grep
:
文件:python_test.py
import re
str='-e ENV_PASSWORD="foo" -e ENV_USER="bar-e sd" -e ENV_DB_NAME="mysite_staging" '
re_pattern='-es+(.*?)="(.*?)"'
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"
文件:bash_test.sh
#!/bin/bash
str='-e ENV_PASSWORD="foo" -e ENV_USER="bar -e sd" -e ENV_DB_NAME="mysite_staging" '
re_pattern='-es+(.*?)="(.*?)"'
array=( $(grep -oP $re_pattern <<<$str) )
for i in ${array[@]}; do
echo $i;
done
将这些值存储在字符串中首先看起来像是一个反模式。看见https://mywiki.wooledge.org/BashFAQ/050
另外,请注意Python和grep
(即使使用-P
(具有不同的regex方言和功能。
假设输入的格式相当严格,我只需在Bash中使用内置的regex支持。
#!/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
该模式包含两个带括号的组(除此之外,它只是将Perl模式重新表述为传统的ERE正则表达式(,第一个组捕获变量,第二个组捕获值;这些捕获组被收集到Bash内置数组BASH_REMATCH
中,然后我们从中取出它们。
这感觉相当脆弱(尤其是循环结束时的参数扩展(,但它适用于您的测试用例。
演示:https://ideone.com/mY4HKI
顺便说一句,在您最初的尝试中,您希望"$(array[@]}"
和echo "$i"
在值周围使用双引号;另请参阅何时在shell变量周围加引号?
一个更好的方法是将配置存储在标准的机器可读格式中,如JSON或YAML,并从中获取。
使用-E
选项而不是-P
:
array=( $(grep -oE $re_pattern <<<$str) )
观看现场演示。