Home > Blockchain >  shell parsing json contains spaces in string
shell parsing json contains spaces in string

Time:10-14

I need to parse json which contains spaces in string in it, but the output value is truncated at spaces.

My Initial.json file is:

{
  "WorkspaceName":"aaa bbb ccc ddd eee",
  "ReportFileName":"xxx yyy zzz",
  "StageName":"sit uat prod"
}

My current shell code is:

InitialFile=$JsonPath/deployment/configuration/Initial.json
data=$(cat $InitialFile | sed -r 's/",/"/' | egrep -v '^[{}]' | sed 's/"//g' | sed 's/:/=/1')
declare $data

echo WorkspaceName is_$WorkspaceName
echo ReportFileName is_$ReportFileName
echo StageName is_$StageName

The result is:

WorkspaceName is_aaa

ReportFileName is_xxx 

StageName is_sit 

The expected reuslt is aaa bbb ccc ddd eee, xxx yyy zzz, sit uat prod instead of aaa, xxx, sit.

How to achieve it? I'm not very familiar with shells, any advice would be greatly appreciated.

Update:

I using following code to resolve this issue:

WorkspaceName=$(grep -o '"WorkspaceName": "[^"]*' configuration/Initial.json | grep -o '[^"]*$')
ReportFileName=$(grep -o '"ReportFileName": "[^"]*' configuration/Initial.json | grep -o '[^"]*$')
StageName=$(grep -o '"StageName": "[^"]*' configuration/Initial.json | grep -o '[^"]*$')

As you can see, this solves the problem, but it doesn't seem perfect, I need to get each variable in the json separately, there will be a lot of repeated statements, when there are many variables in the json, this will be a Very troublesome, so is there a way to simplify it?

CodePudding user response:

Using sed

$ InitialFile="${JsonPath}/deployment/configuration/Initial.json"
$ data=$(sed -En 's/^[^"]*"([^"]*)":"([^"]*).*$/\1 is_\2/p' "$InitialFile")
$ echo "$data"
WorkspaceName is_aaa bbb ccc ddd eee
ReportFileName is_xxx yyy zzz
StageName is_sit uat prod

CodePudding user response:

1st solution(GNU awk): With GNU awk you can try following solution, written and tested with your shown samples only.

awk -v RS='"[^"]*":"[^"]*",?' '
RT{
  sub(/":"/,OFS,RT)
  gsub(/^"|",?$/,"",RT)
  print RT
}
' Input_file


2nd solution: If jq is allowed you can simply do following command. Which OP is saying is not in OP's system but adding it as a variant here.

jq -r 'to_entries[] | "\(.key) \(.value)"' Input_file

With shown samples output will be as follows:

WorkspaceName aaa bbb ccc ddd eee
ReportFileName xxx yyy zzz
StageName sit uat prod

CodePudding user response:

You could use sed and regexp:

eval $(sed -n -e 's/^.*"\(.*\)":\(".*"\).*$/\1=\2/p' $InitialFile)
  • sed will take the filename as an argument
  • -n will make sed not print per default
  • -e 's/<match pattern>/<output>/ a sed command to search and replace (live test).
  • p in case of matching pattern the output is printed
  • eval will evaluate the output as if you would have written it at the prompt. In this case assigning values to some vars.

I think the code above is shorter and better in several ways, but it could of course be done your way with some adjustment, or in several other ways. The main issue with your code is that the assignment needs to be one string, not several. So your code produces this:

WorkspaceName=aaa bbb ccc ddd eee

while it should be:

WorkspaceName="aaa bbb ccc ddd eee"
  • Related