简体   繁体   中英

Find / Replace / Append JSON String in bashscript without using jq

I have a json string and should extract the values in the square brackets with bash script and validate it against the expected values. If the expected value exists, leave as it is or else add the new values into the square brackets as expected.

  "hosts": [“unix://“,”tcp://0.0.0.0:2376"]

I cannot use jq.

Expected :

Verify if the values “unix://“ and ”tcp://0.0.0.0:2376" exists for the key "hosts". Add if it doesn't exist

I tried using like below,

$echo "\"hosts\":[\"unix://\",\"tcp://0.0.0.0:2376\"]" | cut -d: -f2
["unix

$echo "\"hosts\":[\"unix://\",\"tcp://0.0.0.0:2376\"]" | sed 's/:.*//'
"hosts"

I have tried multiple possibilities with sed & cut but cannot achieve what I expect. I'm a shell script beginner.

How can I achieve this with sed or cut?

You need to detect the precense of "unix://" and "tcp://0.0.0.0:2376" in your string. You can do it like this:

#!/bin/bash
#    
string='"hosts": ["unix://","tcp://0.0.0.0:2376"]'

check1=$(echo "$string" | grep -c "unix://")
check2=$(echo "$string" | grep -c "tcp://0.0.0.0:2376")

(( total = check1 + check2 ))

if [[ "$total" -eq 2 ]]
then
    echo "they are both in, nothing to do"
else
    echo "they are NOT both there, fix variable string"
    string='"hosts": ["unix://","tcp://0.0.0.0:2376"]'
fi

grep -c counts how many times a specific string appears. In your case, both strings have to be found once, so adding them together will produce 0, 1 or 2. Only when it is equal to 2 is the string correct.

cut will extract some string based on a certain delimiter. But it is not typically used to verify if a string is in there, grep does that.

sed has many uses, such as replacing text (with 's///' ). But again, grep is the tool that was built to detect strings in other strings (or files).

Now when it comes to adding text, you say that if one of "unix://" or "tcp://0.0.0.0:2376" is missing, add it. Well that comes back to redefining the whole string with the correct values, so just assign it.

Finaly, if you think about it, you want to ensure that string is "hosts": ["unix://","tcp://0.0.0.0:2376"] . So no need to verify anything, just force it through hardcode at the start of your script. The end result will be the same.


Part 2

If you MUST use cut , you could:

#!/bin/bash
# 
string='"hosts": ["unix://","tcp://0.0.0.0:2376"]'

firstelement=$(echo "$string" | cut -d',' -f1 | cut -d'"' -f4
echo $firstelement
# will display unix://

secondelement=$(echo "$string" | cut -d',' -f2 | cut -d'"' -f2
echo $secondelement
# will display tcp://0.0.0.0:2376

Then you can use if statements to compare to your desired values. But note that this approach will fail if you do not have at least 2 elements in your text between the [ ] . Ex. ["unix://"] will fail cut -d',' since there is no ',' character in the string.


Part 3

If you MUST use sed :

#!/bin/bash
# 
string='"hosts": ["unix://","tcp://0.0.0.0:2376"]'

firstelement=$(echo "$string" | sed 's/.*\["\(.*\)",".*/\1/')
echo "$firstelement"
# will output unix://

secondelement=$(echo "$string" | sed 's/.*","\(.*\)"\]/\1/')
echo $secondelement
# will output tcp://0.0.0.0:2376

Again here, the main character to work with is the , .

firstelement explanation

sed 's/.*\["\(.*\)",".*/\1/'
  • .* anything...
  • \[" followed by [ and " . Since [ means something to sed, you have to \ it
  • \(.*\) followed by anything at all ( . matches any character, * matches any number of these characters).
  • "," followed by "," . This only happens for the first element.
  • .* followed by anything
  • \1 keep only the characters enclosed between \( and \)

Similarily, for the second element the s/// is modified to keep only what follows "," , up to the last "] at the end of the string.

Again like with cut above, use if statements to verify if the extracted values are what you wanted.

Again, read my last comments in the first approach, you might not need all this...

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