3

I am trying to make a bash function that will google last output of terminal $_ for me. For example when I try something and I get an error from terminal, instead of copy and pasting the error in google, I would just type google that and it will google the error for me.

It will also support opening google home page and random google search.

function google() {
  if [ $1 == 'that' ]
  then
    open /Applications/Google\ Chrome.app/ "http://www.google.com/search?q= $_";
  elif [ $1 == '' ]
  then
    open /Applications/Google\ Chrome.app/ "http://www.google.com"
  else
    open /Applications/Google\ Chrome.app/ "http://www.google.com/search?q= $@";
  fi
}

When I type google that, I get search result for [. I don't understand why it's not working?

I'm on OSX 10 and using Chrome.

Mohsen
  • 64,437
  • 34
  • 159
  • 186

4 Answers4

5
  1. Don't use [ $foo == 'bar' ], use [ "$foo" = 'bar' ] or [[ "$foo" == 'bar' ]]
  2. Don't use [ $1 == '' ], use [ -z "$1" ]
  3. As jm666 pointed out, but maybe should have emphasized more, $_ is not the last output on your terminal, it is a "[s]pecial variable set to final argument of previous command executed", so your script will never actually do what you want.

All that being said, a slightly cleaner rewrite of your snippet could look like this:

google()
{
    local s="$_"
    local query=

    case "$1" in
        '')   ;;
        that) query="search?q=${s//[[:space:]]/+}" ;;
        *)    s="$*"; query="search?q=${s//[[:space:]]/+}" ;;
    esac

    echo open /Applications/Google\ Chrome.app/ "http://www.google.com/${query}"
}

Example runs:

$ echo "foo bar quux"
foo bar quux
$ google that
open /Applications/Google Chrome.app/ http://www.google.com/search?q=foo+bar+quux

$ google
open /Applications/Google Chrome.app/ http://www.google.com/

$ google foo    bar    quux
open /Applications/Google Chrome.app/ http://www.google.com/search?q=foo+bar+quux
Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71
  • Is there any way that I can read previous `stdout`? I know bash have no access to it, but can we force bash to read all `stdout`s and save them in somewhere then I can use that for my google function? As you pointed out, it will not google multiline outputs – Mohsen May 11 '13 at 18:41
  • @Mohsen: The "correct" answer would be no, the honest answer would be to have a look at the answer to [this question](http://stackoverflow.com/questions/5955577/bash-automatically-capture-output-of-last-executed-command-into-a-variable) which sort of does what you want. But I really advise against hacks like this. (PS: I did not say that it will not capture multiline outputs. It won't capture any (!) output, it captures an argument to your command. It just appears to capture output depending on the command in question.) – Adrian Frühwirth May 11 '13 at 18:56
  • @Mohsen I'm doubt than you really want capture the OUTPUT. Imagine, you will try some command what will output 1000 lines, and you accidentally send this to google. Sure, nothing bad happens, but probably you don't get ANY useful answer. Maybe is worth thinking about capture the STDERR - so, when you doing something wrong - send the eror message to google. But honestly, is is much productive use google manually for the best results. Thanx Adrian for extending the answer with a couple of good points. ;) – clt60 May 11 '13 at 21:09
3

Because last argument of last command is [.

You have to store the last argument in order before doing anything:

function google() {
  local lastarg=$_
  if [ $1 == 'that' ]; then
    open /Applications/Google\ Chrome.app/ "http://www.google.com/search?q= $lastarg"
  ...
techno
  • 525
  • 3
  • 13
3

First, in the bash the $_ mean (see here)

the last argument of the last command

so it will change when you use it in an script. For example the simple function

mytest() {
        if [ "$1" == 'that' ]
        then
                echo $_
        fi
}

will print

]

what is the last argument of the last command (if)

Second, directly adding the url into the google, as the base minimum, you need change spaces to +. And you shouldn't have space between = and the google's query Your script could be simple as:

google() {
        gq=$(sed 's/ /+/g' <<<"$*")
        open -a /Applications/Google\ Chrome.app "http://www.google.com/search?q=$gq";
}

where the sed line changes the spaces into +, so command

google some weird search

will be changed to URL

http://www.google.com/search?q=some+weird+search

After you source the above script, or you put it into ~/.profile, you can use it as:

google $_    #instead of the "that" is shorter anyway :)

to open Chrome with a query of the last argument of the last command, or simple

google

to open chrome with en "empty" search, or as above google some weird search

Third, if you use open something something_other the open will try open both things. So if you want open Chrome, wil argument you should use the -a applcation switch. If your default browser is Chrome and not Safari you can use the simple:

 open "http://www.google.com/search?q=$gq";
clt60
  • 62,119
  • 17
  • 107
  • 194
  • 2
    Would be helpful for me to know what is wrong with my answer, so downvoter, please add some comments. Downvotes are like hugs, it is good to know why.. ;) – clt60 May 11 '13 at 08:04
  • I don't understand why this would get downvoted; it perfectly answers the question and also states that `$_` does not do what the OP thinks it does (even though you could have stressed this way more, as it's quite important regarding the goal/usefulness of the script). – Adrian Frühwirth May 11 '13 at 11:51
1

For my approach I instead used a combination of html2text (available through many things, i used HomeBrew), Curl and Grep Then I created the following function in my BashProfile.

goo() {
    ARGS=''
    if [ "x$1" != "x" ]; then
        for arg in $*
        do
            ARGS="$ARGS $arg"
        done
    else
        read -p "what do you want to search for: " ARGS
    fi
    ARGS=$(echo $ARGS | sed -e 's/\ /+/g')
    printf "\nsearching for the following term: $ARGS \n\n"
    curl -A Chrome http://www.google.com/search?q=$ARGS | html2text | grep ' 1\. \| 2\. \| 3\. ' -A 4 -B1 --color
}

When I am in a terminal all i need to type is 'goo hello world' and this will search for hello+world in google search, returning the top three google hits.

For those not familiar with Grep the -A means 'lines after match found' and -B means before. The --color will highlight the 'matched' terms in the output.

As I seem to spend a lot of my life in terminal i find this command pretty useful.

fuzzyrob
  • 31
  • 3