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.

When I create

alias wd='ps -ef | grep java | awk {'print $2 " " $9'} | egrep "(A|B|C|D)"'

or

function wd () {
    ps -ef | grep java | awk '{print $2}' ...
}

in my .bashrc file, I get errors. Interestingly, if I source my .bashrc file with the function, it 'compiles', but when executing, gives me:

 context is
     >>> \ <<< {\print
    missing }

Can someone help me with this, and also answer when its better to put something in a function versus in an alias?

share|improve this question

3 Answers 3

up vote 3 down vote accepted

Why the alias doesn't work

alias wd='ps -ef | grep java | awk {'print $2 " " $9'} | egrep "(A|B|C|D)"'

The alias command receives three arguments. The first is the string wd=ps -ef | grep java | awk {print (the single quotes prevent the characters between them from having a special meaning). The second argument consists of a single space character. (In .bashrc, the positional parameters $2 and $9 are empty, so $2 expands to a list of 0 words.) The third argument is } | egrep "(A|B|C|D)" (again the single quotes protect the special characters).

The alias definition is parsed like any other shell command when it is encountered. Then the string defined for the alias is parsed when the alias is expanded. Here are some possible ways to define this alias. First possibility: since the whole alias definition is within single quotes, only use double quotes in the commands, which means you must protect the " and $ meant for awk with backslashes.

alias wd='ps -ef | grep java | awk "{print \$2 \" \" \$9}" | egrep "(A|B|C|D)"'

Second possibility: every character stands for itself within single quotes, except that a single quote ends the literal string. '\'' is an idiom for “single quote inside a single-quoted string”: end the single-quoted string, put a literal single quote, and immediately start a new single-quoted string. Since there's no intervening space, it's still the same word.

alias wd='ps -ef | grep java | awk '\''{print $2 " " $9}'\'' | egrep "(A|B|C|D)"'

You can simplify this a bit:

alias wd='ps -ef | grep java | awk '\''{print $2, $9}'\'' | egrep "(A|B|C|D)"'

Tip: use set -x to see how the shell is expanding your commands.

Why the function doesn't work

I don't know. The part you show looks ok. If you still don't understand why your function isn't working after my explanations, copy-paste your code.

Alias or function?

Use an alias only for very simple things, typically to give a shorter name to a frequently-used command or provide default options. Examples:

alias grep='grep --color'
alias cp='cp -i'
alias j=jobs

For anything more complicated, use functions.

What you should have written

Instead of parsing the ps output, make it generate output that suits you.

wd () {
  ps -C java -o pid=,cmd= | egrep "(A|B|C|D)"
}
share|improve this answer

The problem with the alias is that quotes don't nest directly (except, as a special case, inside $()). You need to escape the inner ones.

alias wd='ps -ef | grep java | awk {\'print $2 " " $9\'} | egrep "(A|B|C|D)"'
#                                   ^^               ^^

You've removed too much of the function form for me to be certain, but the error snippet is from awk and suggests quoting or shell variable expansion problems.

As a general rule, functions are more flexible than aliases (you have no control over argument processing with aliases aside from history expansion), but aliases are a little faster, and if you end the alias with a space then the first argument gets expanded as a command (tab completion, etc.) Aliases also don't work in the file they're declared in (to avoid infinite alias expansion loops).

share|improve this answer
1  
Several errors here. Your quoting doesn't work at all: backslashes are not special inside single quotes. (See my answer if you need more explanation.) An alias ending with a space has no influence on completion in bash (I think). Aliases do work as soon as they are declared (or in bash, maybe only on the next line, but that's a bug); alias expansion loops are prevented by a completely different mechanism (an alias foo is not expanded in the (direct or indirect) result of the expansion of foo). –  Gilles Mar 18 '11 at 19:20

I dont think you can pass an argument to an alias. An alias is just a string replacement rule for the first word of a command.
Example:

alias wd='ps -ef | grep java | awk {'print $2 " " $9'} | egrep "(A|B|C|D)"'

will result in the command wd arg1 arg2 arg3 being replaced and executed as

ps -ef | grep java | awk {'print " " '} | egrep "(A|B|C|D)" arg1 arg2 arg3

For everything beyond that, use functions.

share|improve this answer
    
Actually, because $2 and $9 are inside single quotes, they won't be expanded by the shell but by awk, which uses them as field selectors for the ps output: the uid and the first argument to the command, for Linux ps -f. That said, the failed nested quoting means the shell was expanding them when it shouldn't have been. –  geekosaur Mar 18 '11 at 18:53
    
@geekosaur oh, yes, of course. I haven't looked at it that way. –  artistoex Mar 18 '11 at 18:58
    
@geekosaur, @artistoex: Yes, you can pass an argument to an alias, and in fact it's commonly used. Here, $2 and $9 are unprotected when the alias is defined. See my answer for the full story. –  Gilles Mar 18 '11 at 19:22
    
@gilles The argument is not passed to the alias in the sense you can not effect where the original arguments will be placed in the final command string. It will always be placed at the end. –  artistoex Mar 19 '11 at 10:30

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.