0

I have a string like this below ( basically response of an HTTP request ).

response={"@base":"http://localhost:8080/hello/stackoverflow/","updated":"2016-01-20T17:12:02.284Z","links":[{"rel":"self","href":"/0"}],"content":{"id":"0","enabled":true}}

Now i have a shell script where i am capturing this http response and parsing this just to extract value of variable 'enabled' here. I have this code written but it does seems to be working. I am very new to shell so not really sure if i am doing something completely wrong or missing any specific detail.

enabled=$(echo $response | awk -F"," '/content/ {
    for( i=1; i < NF; i++) {
       if( match( $i, /enabled/) ){
           split( $i, a, ":")
           print a[length(a)]
       }
    }
  }')

Can someone suggest best way to do it or any other suggestion to capture the value of tag 'enabled' in response of http request. enabled tag will always be present under tag 'content'

NOTE: I did researched and try understanding the shell script. This is how i was able to write the above code. but something does not seems to be correct so i never get the value of the tag enabled.

Any guidance or suggestion is appreciated

user1188611
  • 945
  • 2
  • 14
  • 38
  • 2
    Have you considered using `jq`? – anubhava Jan 20 '16 at 17:39
  • I cant use jq that is not installed in environment. I need to do it using shell scripting itself – user1188611 Jan 20 '16 at 18:07
  • 1
    You're not the first person to be in that situation, which is why we have many (many!) questions in the knowledgebase already where it's asked and answered. No need for another. – Charles Duffy Jan 20 '16 at 18:17
  • BTW, do you have Python available? There's a JSON library included in the Python interpreter even back to some very old releases. – Charles Duffy Jan 20 '16 at 18:19
  • 2
    @toolic, why delete your answer? The OP may not have liked it, but answers are for everyone, not just them; I'd certainly be happy to give it my upvote. – Charles Duffy Jan 20 '16 at 18:21
  • this code is being run from a shell script. So i need something which i can use within .sh file and get the value of a specific tag. I can use python or something else, but as i have said in my other comments this is a very old legacy code so cant make such – user1188611 Jan 20 '16 at 18:22
  • @toolic: answers you all are suggesting is great. Its just that not applicable to what i am looking for. But you should leave the answer as others might find it useful for similar problem – user1188611 Jan 20 '16 at 18:23
  • 1
    @user1188611, if you think you can't embed Python or Perl code in a shell script, you are simply wrong. – Charles Duffy Jan 20 '16 at 18:23
  • I can but not for this solution that is what i am trying to say – user1188611 Jan 20 '16 at 18:24
  • 1
    Really? Which version, *specifically*, of Python is installed on your target machine? Which version, *specifically*, of Perl? I mean, Perl has been a de facto standard component on UNIX systems since the 80s; unless you're on an embedded system, it'll be there. I could believe that you had a really ancient Python (1.5.2 or such), or a Perl with no nonstandard modules; I'm a little more incredulous as to the claim that you have none at all. – Charles Duffy Jan 20 '16 at 18:24
  • 1
    This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-thread-multi – user1188611 Jan 20 '16 at 18:25
  • 2
    @user1188611 It's bad form to ask a question and then dismiss answers that don't fit into your constraints when you **haven't previously mentioned those constraints** in your question. – Matt Jacob Jan 20 '16 at 18:27
  • 5.18.2? That's actually from this decade, even. If you have any Python interpreter less than 10 years older than your Perl release, it'll have JSON support built-in, so you'll be able to use a Python-based answer from one of the many aforementioned duplicates of this question. – Charles Duffy Jan 20 '16 at 18:28
  • @MattJacob: i havent dismiss any answers or downvote anything. As i said perl tag got added by mistake and as soon as reliaze i have updated the question – user1188611 Jan 20 '16 at 18:29
  • Thank you for all the responses and help. I was able to fix the issue i had by using AWK. Played a bit more and it worked. – user1188611 Jan 20 '16 at 19:10
  • 2
    @user1188611, ...for a questionable version of "worked". Look at what your `awk` does if `enabled` comes before `id` inside the `content` hash. Look at what happens if you try to use your existing code to extract a string that has a comma or a colon or escaped quotes inside of it. There's a reason we strongly encourage people to use a real JSON parser: The roll-your-own approach is inevitably buggy. – Charles Duffy Jan 20 '16 at 20:35

2 Answers2

2

Where response={...} is your full JSON string:

$ echo 'response={...}' | perl -MJSON::PP -wne 's/^[^{]+//; print decode_json($_)->{content}->{enabled};'  
1

If you have Perl 5.18.2 as you say, then using JSON::PP shouldn't be a problem:

$ corelist -a JSON::PP

Data for 2015-12-21
JSON::PP was first released with perl v5.13.9
  v5.13.9    2.27103
  v5.13.10   2.27103
  v5.13.11   2.27105
  v5.14.0    2.27105
  ...
  v5.18.0    2.27202
  v5.18.1    2.27202
  v5.18.2    2.27202
  v5.18.3    2.27202
Matt Jacob
  • 6,503
  • 2
  • 24
  • 27
  • same as my other comments. I cant use the new library as you mentioned -MJSON::XS – user1188611 Jan 20 '16 at 18:10
  • @user1188611 If you didn't want a Perl solution, you probably shouldn't have tagged your question [tag:perl]... ಠ_ಠ – Matt Jacob Jan 20 '16 at 18:19
  • @user1188611, ...can you use `-MJSON`? – Charles Duffy Jan 20 '16 at 18:20
  • 2
    @user1188611 What about JSON::PP? (See my edited answer) – Matt Jacob Jan 20 '16 at 18:44
  • actually my code started working as soon as I have put condition as i=1; i <= NF; i++ instated of i=1; i < NF; i++. But i am getting output value as True}}. That is extra '}}', if you can remove that i will accept your answer – user1188611 Jan 20 '16 at 19:37
  • you wanted to accept your answer so I am asking if you suggest better solution i can accept your answer – user1188611 Jan 20 '16 at 19:41
  • @user1188611 Did you even try running Matt's code? It does exactly what you ask for. – ThisSuitIsBlackNot Jan 20 '16 at 19:42
  • @user1188611 I don't think we're talking about the same code. – Matt Jacob Jan 20 '16 at 19:42
  • Right now after i made the fix, i am getting value of enabled as 'true}}'. I can remove that value using another split. That does not sound a clean solution to me. So i said if you can suggest better i can accept your solution. – user1188611 Jan 20 '16 at 19:42
  • yes i did, but i cant use the JSON:PP so that is why i tried making changed within my code and was able to make it work – user1188611 Jan 20 '16 at 19:43
  • 2
    @user1188611 "i cant use the JSON:PP" Why not? It's a core module in your version of Perl, so it should already be installed on your system. Did you get an error when you ran it? If so, what was the exact error text? (By the way, it's JSON::PP, with two colons, not one.) – ThisSuitIsBlackNot Jan 20 '16 at 20:20
  • 2
    @user1188611, making assistance with unrelated code (particularly, unrelated code that someone is *trying to encourage you not to use*) a condition of acceptance of an answer is... not exactly good form. If a variant of your `awk`-based approach is what you're using, post it as an answer yourself, and accept it. I wouldn't expect it to get much by way of upvotes (rather the contrary), but that's the proper way to handle the situation. That said, I'm similarly curious as to why you can't use a module bundled in the standard library of the Perl release you already told us you had installed. – Charles Duffy Jan 20 '16 at 20:40
  • @CharlesDuffy: i agree to what you are saying but i think you misinterpreted me. What i mean is if you can post or update the solution then i can accept your answer. That is what i mean not the way you interpreted. Yes i will post working solution in sometime. – user1188611 Jan 20 '16 at 20:58
2

Using jq from your shell script, this is simply:

enabled=$(jq -r '.content.enabled' <<<"$response")

...or, if you're targeting POSIX sh and don't have <<<:

enabled=$(printf '%s\n' "$response" | jq -r '.content.enabled')
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • I cant use jq. I did saw this option when i was doing research. Its a very old machine on which this code is running and i cant install new stuff. I need to solve using regular awk or something like that. That is why i used that approach – user1188611 Jan 20 '16 at 18:09