简体   繁体   中英

SubString extraction from a variable in bash

I have this variable called var, whose value is as shown below.

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

From this output , I need to extract the values of

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

The below one just extracting keys. I want to extract the keys into variables.

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

if I

echo $active_production_dc

then it should return

sc-tx2

Something like that. Basically the value for active_production_dc should be saved inside the variable.

Answer for original question

Let's start with your variable:

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

Using jq

jq does not accept the string as is. We must first replace the single-quotes with double-quotes. Then we can extract the keys:

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

Using awk

Using awk to extract the keys:

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

Using awk to extract the values that correspond to those keys:

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

Answer for revised question

For the revised question, we need a new var :

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

We can create shell variables named after the keys like this:

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

When this is done the keys and values are accessible:

$ echo "$active_production_dc"
sc-tx2

Alternatively, and probably preferably, we can make the keys and values available in bash via an associative array. Use:

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

When this is run, using the value for var in the revised question, then the resulting a contains the keys and values:

$ 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" )'

An individual value can be accessed via its key:

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

Using grep -P you can do:

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

However your input appears to be a JSON and you should consider using jq to parse it reliably.

A second on using jq to parse the JSON, but if you are required to parse it in bash, then a second option is an array, controlling the IFS (internal field separator) and parameter expansion with substring removal . Use jq in practice:

#!/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[@]}

Output

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM