1

I'm tying to alias a set of pipe commands, went thru some of the threads here and found that cmd line should be used differently. instead of $1 use !:1 but it doesn't seem to work for me in the below context

This is my set of cmds that I'm wanting to alias (its calculating median)

shell>  cat file_with_numbers| awk '{print $1}' | sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'
shell> 1.15

I want to alias the below part as "median"

sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

so I can just use

shell> cat file_with_numbers| awk '{print $1}' | median

alias median 'sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }''

Badly placed ()'s. //single quotes errored out

alias median "sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

cat file| awk '{print $5}'|  median
awk:  { a[i++]=; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }
awk:           ^ syntax error

so I switched to \!:1 & tried the following and it still didn't work. how can I have this aliased properly?

1> trial 1

alias median "sort -n | awk ' { a[i++]=\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "


cat file|  awk '{print $5}' | median
Bad ! arg selector.

2> trial 2

alias median "sort -n | awk ' { a[i++]=\\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "

cat file| awk '{print $5}' | median
awk:  { a[i++]=!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }
awk:            ^ syntax error

trial 3>

  • If the alias is just going to be in a .bashrc or .profile file, you could also build a complex function in that file, and then call the function from the command line, or build an alias to the function. – Tim Kennedy Aug 28 '18 at 15:25
  • 2
    @Tim, the alias mediam "..." syntax and the shell> prompt suggest the OP is using csh or tcsh. I've edited the question to make it clearer. – Stéphane Chazelas Aug 28 '18 at 16:34
1

Unless you care about reinventing the wheel, you could also use GNU datamash:

alias median 'datamash median 1'

datamash expects tab delimited columns, though you can change the delimiter with -t.

For your particular problem, note that $parameter expansion in (t)csh is done inside double quotes, but contrary to Bourne-like shells, it can't be disabled with backslashes, so you'd need something like:

alias median "sort -n | awk '{a[NR]="\$"1}; END {x = int(NR/2); print NR % 2 ? a[x+1] : (a[x]+a[x+1])/2}'"

That is get out of the double quotes to enter the $ as \$, or go with Mark's approach and use single quotes but get out of them to enter literal single quotes.

1

You can put a single-line command sequence in an alias, but you may need to add backslashes and single or double quotes here and there. But unless you need to invoke the alias with parameters or elements from the shell's history, or need to maximize speed, sometimes it's easier to just put the command sequence as-is into a file, mark it as executable, and place it somewhere in your search path ($PATH or $path).

But to make the following into an alias:

sort -n | awk '{ a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

You need to make sure that

  • the pipeline operator is within a string that is enclosed by quotes; otherwise it will terminate the alias command
  • the $ is either within a string that is enclosed by single quotes, or is outside of any quoted string and is preceded by a \ (thanks, Stéphane, for the alternative)
  • there are no nested single quotes

Don't use \!:1 to try to produce $1. \!:1 would be used if you passed a parameter to your alias. You just want the literal $1 to be seen by awk.

The safest thing to do in this case is to enclose as much of the alias as possible with single quotes, and use " only to surround a literal single quote. You'll see two occurrences of "'" below.

ubuntu% alias median 'sort -n | awk '"'"'{ a[i++]=$1 ; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }'"'"

ubuntu% seq 1 9 | median
5
0

Try this:

$ alias median="sort -n|awk ' { a[i++]="\$1"; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

$ cat file_with_numbers| awk '{print $1}'|median
  • 1
    To fully qualify as a useful answer, please explain your solution. – Kusalananda Aug 28 '18 at 15:24
  • Note that the OP seems to be using csh or tcsh. alias a=cmd is ksh/POSIX syntax. – Stéphane Chazelas Aug 28 '18 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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