从bash中的变量中提取SubString

时间:2016-07-25 05:37:37

标签: linux bash shell sh

我有一个名为var的变量,其值如下所示。

$ echo $var   
{'active_production_dc':'sc-tx2','standby_production_dc':'sc_tx3','active_integration_dc':'int_tx3','standby_integration-dc':'int_va1'}

从这个输出中,我需要提取

的值
'active_production_dc', 
'standby_production_dc', 
'active_integration_dc' and 
'standby_integration_dc' into four different variables.

以下只提取密钥。我想将密钥提取到变量中。

printf "%s" "$var" | awk 'NR>1 && NR%2' RS="({'|'.'|'})"

如果我

echo $active_production_dc

然后它应该返回

sc-tx2

这样的事情。 基本上,active_production_dc的值应该保存在变量中。

3 个答案:

答案 0 :(得分:1)

回答原始问题

让我们从您的变量开始:

$ echo "$var"
{'active-production-dc':'sc-tx2','standby-production-dc':'sc-tx3','active-integration-dc':'int-tx3','standby-integration-dc':'int-va1'}

使用jq

jq不接受字符串。我们必须首先用双引号替换单引号。然后我们可以提取密钥:

$ echo "$var" | sed 's/'\''/"/g' | jq keys
[
  "active-integration-dc",
  "active-production-dc",
  "standby-integration-dc",
  "standby-production-dc"
]

使用awk

使用awk提取密钥:

$ printf "%s" "$var" | awk 'NR%2==0' RS="({'|'.'|'})"
active-production-dc
standby-production-dc
active-integration-dc
standby-integration-dc

使用awk提取与这些键对应的值:

$ printf "%s" "$var" | awk 'NR>1 && NR%2' RS="({'|'.'|'})"
sc-tx2
sc-tx3
int-tx3
int-va1

回答修订后的问题

对于修订后的问题,我们需要一个新的var

$ echo "$var"
{'active_production_dc':'sc-tx2','standby_production_dc':'sc_tx3','active_integration_dc':'int_tx3','standby_integration_dc':'int_va1'}

我们可以创建以这样的键命名的shell变量:

$ while IFS=":" read -r -d, key val; do declare "$key=$val"; done < <(echo "$var" | sed "s/[{}']//g; s/$/,/")

完成此操作后,可以访问键和值:

$ echo "$active_production_dc"
sc-tx2

或者,可能最好,我们可以通过关联数组使bash中的键和值可用。使用:

declare -A a
while IFS=":" read -r -d, key val
do
    a["$key"]="$val"
done < <(echo "$var" | sed "s/[{}']//g; s/$/,/")

运行此操作后,在修订后的问题中使用var的值,结果a包含键和值:

$ declare -p a
declare -A a='([standby_integration_dc]="int_va1" [active_production_dc]="sc-tx2" [active_integration_dc]="int_tx3" [standby_production_dc]="sc_tx3" )'

可以通过密钥访问单个值:

$ echo "${a[active_production_dc]}"
sc-tx2

答案 1 :(得分:0)

使用grep -P即可:

arr=($(grep -Po '(?<=[{,])[a-zA-Z0-9-]+' <<< "$s"))

# print resulting array
printf "%s\n" "${arr[@]}"
active-production-dc
standby-production-dc
active-integration-dc
standby-integration-dc

但是您的输入似乎是JSON,您应该考虑使用jq来可靠地解析它。

答案 2 :(得分:0)

使用jq解析JSON的第二步,但是如果你需要在bash中解析它,那么第二个选项是一个数组,控制IFS(内部字段分隔符)和< em>参数扩展,带子串删除。在实践中使用jq

#!/bin/bash

var="{'active-production-dc':'sc-tx2','standby-production-dc':'sc-tx3',\
'active-integration-dc':'int-tx3','standby-integration-dc':'int-va1'}"

IFS=$','
a=( $(echo "$var") )

for ((i = 0; i < ${#a[@]}; i++)); do 
    b=${a[i]}
    b=${b#*\{}
    b=${b%\}*}
    a[i]="${b%:*}"
done

printf "%s\n" ${a[@]}

<强>输出

$ bash parsevar.sh
'active-production-dc'
'standby-production-dc'
'active-integration-dc'
'standby-integration-dc'