9

I'm trying to create an alias for a command to see the memory use,

ps -u user -o rss,command | grep -v peruser | awk '{sum+=$1} END {print sum/1024}'

but, the naive,

#.bash_aliases
alias totalmem='ps -u user -o rss,command | grep -v peruser | awk '{sum+=$1} END {print sum/1024}''

gives errors:

-bash: alias: END: not found
-bash: alias: {print: not found
-bash: alias: sum/1024}: not found

I've tried with double quotes,

totalmem ="ps ... |awk '{sum+=$1} END {print sum/1024}'", or

totalmem ='ps ... |awk "{sum+=$1} END {print sum/1024}"', escaping,

totalmem ='ps ... |awk \'{sum+=$1} END {print sum/1024}\'', or escaping double quotes ... but I can't seem to make it work.

totalmem ='ps ... |awk \"{sum+=$1} END {print sum/1024}\"',

gives the error

awk: "{sum+=}
awk: ^ unterminated string

Any tips appreciated.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Massagran
  • 1,781
  • 1
  • 20
  • 29
  • 1
    http://www.unix.com/shell-programming-scripting/38249-define-alias-embeded-awk-command.html – Can Geliş Jan 28 '13 at 11:16
  • 2
    Never need `grep` with `awk '$0!~/peruser/{sum+=$1}END{print sum/1024}'` – Chris Seymour Jan 28 '13 at 11:22
  • 1
    @Massagran, ...insofar as you're still around -- I'd like to encourage you to think about switching over to the answer suggesting a function, which avoids the problem altogether. (Functions are far more powerful than aliases -- they can perform conditional logic; they have their own call stack entry with an argument list; they can be exported to the environment; they work inside scripts by default, which aliases don't; etc). The [#bash IRC channel factoid on aliases](https://wooledge.org/~greybot/meta/alias) has long said "if you have to ask, use a function instead". Those are wise words. – Charles Duffy Sep 01 '22 at 15:15

3 Answers3

20

You can avoid quoting issues by using a shell function instead of an alias:

totalmem () {
  ps -u user -o rss,command | grep -v peruser | awk '{sum+=$1} END {print sum/1024}'
}

This is also more flexible, as you could allow totalmem to take arguments, such as a user name to pass to the -u option of ps, as in this example:

totalmem () {
  ps -u "$1" -o rss,command | grep -v peruser | awk '{sum+=$1} END {print sum/1024}'
}
chepner
  • 497,756
  • 71
  • 530
  • 681
12

You almost have it, the $ will be expanded in double-quotes, so that needs extra escaping:

alias totalmem='ps -u user -o rss,command | grep -v peruser | awk "{sum+=\$1} END {print sum/1024}"'

Or with the pattern inside awk as suggested by iiSeymour:

alias totalmem='ps -u user -o rss,command | awk "!/peruser/ {sum+=\$1} END {print sum/1024}"'
Thor
  • 45,082
  • 11
  • 119
  • 130
  • 4
    thanks god of the hammer. I had just found a solution with `alias memuse='ps -u user -o rss,command | grep -v peruser | awk '"'"'{sum+=$1} END {print sum/1024}'"'"''` but yours is cleaner – Massagran Jan 28 '13 at 11:30
  • 1
    @Massagran Thank you Massagran from me a macOS user. You just save my day. – Randy Lam Jul 19 '21 at 06:38
9

Like this:

alias totalmem='ps -u user -o rss,command | grep -v peruser | awk '\''{sum+=$1} END {print sum/1024}'\'

Explanation: you may use different kind of quotes for the same argument, like "I'm double-quoted"'and I am $HOME-less'-and-i-am-not-quoted. Hence if you need a single quote inside single quotes, you can add '\'' which (1) terminates single quoting, (2) adds literal single quote with \', (3) starts single quoting again.

(Aliases of this size are something that's better done as functions).

Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69