Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

In Mac Terminal, I'm trying to parse the "name" out of this JSON response:

{"created_at":"2012-08-27T20:04:27Z","deleted_at":null,"id":21462840,"item_type":"video","name":"CastingBy-v12 mixed.mov","private":true,"redirect_url":null,"remote_url":"http://f.cl.ly/items/3D0P02b3e3p2I/CastingBy-v12%20mixed.mov","source":"Cloud/1.5.4 CFNetwork/520.4.3 Darwin/11.4.0 (x86_64) (MacPro5%2C1)","updated_at":"2012-08-27T20:13:38Z","view_counter":2,"href":"http://my.cl.ly/items/2840","icon":"http://my.cld.me/images/item-types/video.png","subscribed":true,"url":"http://files.housenyc.com/1I3E2F3C","content_url":"http://files.eeehousenyc.com/1I3Q0Z1E2F3C/CastingBy-v12%20mixed.mov","download_url":"http://files.eeehousenyc.com/1I3Q0F3C/download/CastingBy-v12%20mixed.mov","gauge_id":null}

I'm using

sed 's/{.*?"name":"\(.+?\)".*/\1/'

but it returns the whole string.

I want it to return just

CastingBy-v12 mixed.mov

share|improve this question
1  
Can you use Python, instead? –  Keith Aug 27 '12 at 22:09
add comment

5 Answers 5

up vote 3 down vote accepted

This is the expression you are looking for:

sed -e 's/^.*"name":"\([^"]*\)".*$/\1/' infile

It results to:

CastingBy-v12 mixed.mov

In yours there are several errors:

  • In sed only greeding expression can be used: .*? and .+? are incorrect.
  • The + must be escaped.
  • Use [^"]* to avoid that the regular expression matches until last double quotes of the string.
share|improve this answer
    
Thanks for all the tips! But that still returns the entire string. I'm using echo "{my big string}" | sed 's/^.*"name":"\([^"]\+\)".*$/\1/' –  Ze'ev Aug 27 '12 at 21:53
    
@Ze'ev: Sorry. It works for me and I cannot catch the issue that doesn't work for you. –  Birei Aug 27 '12 at 22:03
    
Maybe because I'm on Mac using Terminal? –  Ze'ev Aug 27 '12 at 22:14
1  
@zeev, Yes, Mac uses a BSD sed that doesn't have all the gnu features. I tested a bit and it seems Mac's sed doesn't recognize either + or \+. Change that to * . –  Kevin Aug 27 '12 at 23:24
    
@Kevin AHA! That did it! Thanks! | sed 's/^.*"name":"\([^"]*\)".*$/\1/' –  Ze'ev Aug 28 '12 at 3:29
add comment

Parsing json with just sed is as problematic as parsing HTML - in short: since elements can embed other elements and regex doesn't support recursion, it's essentially impossible to parse correctly with just regexp.

There's a PCRE solution to parsing and validating json here: http://stackoverflow.com/questions/2583472/regex-to-validate-json - I haven't used or tested it so I'll have to take the author's word that it works...but PCRE does a lot of things that just aren't in the basic or extended regexps supported by sed.

In any case, IMO you're better off using perl or python or awk and one of the json parsing libs for those languages, or a specialised json parsing tool - several are mentioned here:

http://stackoverflow.com/questions/3858671/unix-command-line-json-parser

Any of them can be used to extract data from JSON input for use in a shell script. Or you could write your entire program within that language.

For example, piping your json data into python -mjson.tool results in this:

$ echo "JSONDATAHERE" | python -m json.tool
{
    "content_url": "http://files.eeehousenyc.com/1I3Q0Z1E2F3C/CastingBy-v12%20mixed.mov", 
    "created_at": "2012-08-27T20:04:27Z", 
    "deleted_at": null, 
    "download_url": "http://files.eeehousenyc.com/1I3Q0F3C/download/CastingBy-v12%20mixed.mov", 
    "gauge_id": null, 
    "href": "http://my.cl.ly/items/2840", 
    "icon": "http://my.cld.me/images/item-types/video.png", 
    "id": 21462840, 
    "item_type": "video", 
    "name": "CastingBy-v12 mixed.mov", 
    "private": true, 
    "redirect_url": null, 
    "remote_url": "http://f.cl.ly/items/3D0P02b3e3p2I/CastingBy-v12%20mixed.mov", 
    "source": "Cloud/1.5.4 CFNetwork/520.4.3 Darwin/11.4.0 (x86_64) (MacPro5%2C1)", 
    "subscribed": true, 
    "updated_at": "2012-08-27T20:13:38Z", 
    "url": "http://files.housenyc.com/1I3E2F3C", 
    "view_counter": 2
}

which you can then pipe into sed like this:

$ echo "JSONDATAHERE" | python -m json.tool | sed -n -e '/"name":/ s/^.*"\(.*\)".*/\1/p'
CastingBy-v12 mixed.mov

Relying on the greedy nature of regexp, the sed script extracts everything between the second-last " and the last " character on any line containing "name":.

share|improve this answer
    
BTW, yes I have used regexps to parse HTML and JSON. I've even made it work for my specific needs at the time...but I know that what I did was fragile and prone to failure and highly sensitive to the input data. These days I usually find it easier and far more reliable to pre-process the json data with python -m json.tool and then pipe that into sed or awk. or just write a perl script using the JSON module. I'll still use regexps for a quick and dirty one-liner hack, but for anything intended to be used repeatedly, I'll do it properly. –  cas Aug 27 '12 at 22:21
add comment

This dosn't answer your question directly. But if you need to do such things on a regular basis, consider using a generally available programming language like Perl, Python, Ruby.

In Ruby, your solution would be:

some_command_that_emits_json | ruby -e "require 'rubygems';require 'json'; output=JSON.parse(STDIN.gets); puts output['name']"

share|improve this answer
add comment

Going from this thread, this does the trick:

echo {json...foo} | awk -F=":" -v RS="," '$1~/"name"/ {print}' | sed 's/\"//g' | sed 's/name://'

share|improve this answer
    
You probably want RS="," to become RS=",|{|}"; in case what you are looking for is at the beginning or end of the line. –  A T Feb 3 at 4:24
add comment

Here's one way to do it with the JSON module of perl:

 json_producing_process | perl -MJSON -lne 'print from_json($_)->{name}'
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.