Work the Shell - Exploring Lat/Lon with Shell Scripts
With the rise of geolocation systems on mobile devices (think “around me” on the Apple iPhone), a consistent method of measuring points on Earth has become quite important. The standard that's used is latitude and longitude, which measure the distance north or south of the equator and the distance east or west of the prime meridian (which goes through Greenwich, England). Your GPS devices all understand this notation, as does Google Maps, Yahoo Maps, MapQuest and so on.
From a shell scripting perspective, we're interested in both being able to identify lat/lon for a point on the Earth and then, armed with that information, to see if we can calculate the distance between two points on the planet.
The first seems almost insurmountably hard until you learn that Yahoo Maps has a very simple API that lets you specify a URL that includes a street address and returns an XML object that includes its lat/lon values.
For example, you might be familiar with 1600 Pennsylvania Avenue, Washington, DC. I know you've seen pictures of the place. What's its lat/lon?
$ u='http://api.maps.yahoo.com/ajax/geocode'
$ a='?appid=onestep&qt=1&id=m&qs=1600+pennsylvania+ave+washington+dc'
$ curl "$u$a"
YGeoCode.getMap({"GeoID" : "m",
"GeoAddress" : "1600 pennsylvania ave washington dc",
"GeoPoint" : {"Lat" : 38.89859,
"Lon" : -77.035971},
"GeoMID" : false,
"success" : 1} ,1);
<!-- xm6.maps.re3.yahoo.com uncompressed/chunked
Tue Aug 4 12:16:51 PDT 2009 -->
Note that the output actually comes back as two lines; the the data above, and in the other examples, has been reformatted to make it more readable.
Skim that return object, and you'll see Latitude = 38.89859 and Longitude = -77.035971. Feed those two into Google Maps as “38.89859,-77.035971” as a check, and you'll find the image shown in Figure 1.
You guessed it, it's the street address of the White House.
Let's start by creating a simple script where you can specify a street address and it will output lat/lon values.
The first part is easy: take whatever was specified on the command line, and “recode” it to be URL-friendly. Then, append that to the Yahoo API URL, and output the results of a curl call:
#!/bin/sh url='http://api.maps.yahoo.com/ajax/geocode' args='?appid=onestep&qt=1&id=m&qs=' converter="$url$args" addr="$(echo $* | sed 's/ /+/g')" curl -s "$converter$addr" exit 0
Let's test it with a different address this time:
$ sh whereis.sh 2001 Blake Street, Denver, CO
YGeoCode.getMap({"GeoID" : "m",
"GeoAddress" : "2001 Blake Street, Denver, CO",
"GeoPoint" : {"Lat" : 39.754386,
"Lon" : -104.994261},
"GeoMID" : false,
"success" : 1}, 1);
<!-- x1.maps.sp1.yahoo.com uncompressed/chunked
Tue Aug 4 12:37:44 PDT 2009 -->
You can figure out what's at this address if you like. More important, you can see that this simple four-line script does the job—sort of.
What we really want, however, is to extract just the lat and lon values and toss everything else out. This can be done with a bunch of different tools, of course, including Perl and awk, but I'm a rebel, so I use cut instead.
To do this, we need to count the double quotes (") in the output block. The 12th double quote is immediately before the latitude value, and the 15th is immediately after the longitude value. If we just worked with that, we would get:
$ sh whereis.sh 2001 Blake Street, Denver, CO | cut -d\" -f13-15 :39.754386,"Lon":-104.994261},
Okay, so that's most of the work. Better, though, is to specify two different specific fields (13,15 rather than 13-15):
$ sh whereis.sh 2001 Blake Street, Denver, CO | cut -d\" -f13,15 :39.754386,":-104.994261},
That's 99% of what we want. Now we just need to clean up the noise. To do that, I'll jump back into the script itself, rather than experimenting on the command line:
curl -s "$converter$addr" | \
cut -d\" -f13,15 | \
sed 's/[^0-9\.\,\-]//g'
And testing:
$ sh whereis.sh 2001 Blake Street, Denver, CO 39.754386,104.994261,
Almost. Really, really close. But, that last comma is not wanted. Hmmm....
Okay! To delete the last comma, we simply need to add a second substitution to the sed statement, so that the full sed expression is now:
sed 's/[^0-9\.\,\-]//g;s/,$//'
Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- seo services in india
1 hour 54 min ago - For KDE install kio-mtp
1 hour 55 min ago - Evernote is much more...
3 hours 55 min ago - Reply to comment | Linux Journal
12 hours 41 min ago - Dynamic DNS
13 hours 15 min ago - Reply to comment | Linux Journal
14 hours 13 min ago - Reply to comment | Linux Journal
15 hours 3 min ago - Not free anymore
19 hours 5 min ago - Great
22 hours 53 min ago - Reply to comment | Linux Journal
23 hours 1 min ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?





Comments
error?
When I run this script I get:
whereis: 7: Syntax error: Unterminated quoted string
Here is the script as I have it:
#!/bin/sh url='http://api.maps.yahoo.com/ajax/geocode' args='?appid=onestep&qt=1&id=m&qs=" converter="$url$args" addr="$(echo $* | sed 's/ /+/g')" curl -s "$CONVERTER$ADDR" | \ sed -e 's/.*{\("Lat":[^}]*\).*/\1/' -e 's/"L.."://g' exit 0Here is the command I'm running:
sh whereis 2001 Blake Street, Denver, CO
This seems pretty simple but I cannot see what I'm missing.
Cupla Problems
You've got a couple problems in your script, the one that's giving you the error is here:
You've got a string with mismatched quotes: it starts with a single quote and ends with a double quote, you need this:
or this
The other problem is that the shell is case sensitive, so you can't use "converter" and "CONVERTER" interchangeably, pick one. Same with "addr" and "ADDR". So change:
to
p.s. The first error (the mismatched quotes) was in the original text, it has now been fixed.
Mitch Frazier is an Associate Editor for Linux Journal.
What about bad addresses?
Is there any way to tell if the address you input is invalid? I've tried a few made-up bad addresses and it still seems to give valid lat/lon coordinates.
bad address
That's a "Feature" of yahoo's service. They'll give you their best estimate. If the house number is bad, they'll tell you the location of the street; if the street is bad, they'll tell you the location of the city; if the city is bad, they'll tell you the location of the state....
To tell if the address is bad you could, perhaps, compare the results with the results of a less specific look up.
shell errors
As written, I get only longitude.
when I change the sed to...
cut -d\" -f11,13 | \
I get the expected output
$ cat whereis.sh
#!/bin/bash
URL='http://api.maps.yahoo.com/ajax/geocode'
ARGS='?appid=onestep&qt=1&d=m&qs='
CONVERTER="$URL$ARGS"
ADDR="$(echo $* | sed 's/ /+/g')"
curl -s "$CONVERTER$ADDR" | \
cut -d\" -f11,13 | \
sed 's/[^0-9\.\,\-]//g;s/,$//'
exit 0
$ ./whereis.sh 1313 S Disneyland Drive, Anaheim, CA
33.814413,-117.924424
Response Is Different
The response you're getting is different, the GeoID value is not a quoted value as above. The following would avoid problems related to quotes:
curl -s "$CONVERTER$ADDR" | \ sed -e 's/.*{\("Lat":[^}]*\).*/\1/' -e 's/"L.."://g'Mitch Frazier is an Associate Editor for Linux Journal.