3

I had seen someone use a bash alias or function based on awk, which I liked for its simplicity, but can't remember how to implement it (in bash).

Lets say you have a large formatted file, from which you need to pick say 3, 4, 7th column.

For this you can do:

cat bigfile.txt | awk '{print $3, $4, $7}' |less

I need an alias (or function) pawk, which I can use it as:

cat bigfile.txt | pawk 3,4,7 | less

to get the same effect. Number of columns can be arbitrary and may include NF. I tried couple of things to implement this but can't figure out how to pass arbitrary number of variables to awk.

  • Are you sure it was an alias and not a function? I don't think you can pass multiple argument to aliases. – nobe4 May 11 '16 at 14:19
  • I am not sure, but if it was a function it was quite small as well – Tarundeep Singh May 11 '16 at 14:24
2

You can use a function like so:

function pawk(){
  awkString="{print "

  for var in "$@"
  do
    awkString+=" \$$var"
  done

  awkString+=" }"

  awk "$awkString"
}

Example:

cat bigfile.txt | pawk 3 4 7 | less
  • 1
    If the output fields indeed need no separator between them, this can be reduced to function pawk() { awk "{print ${*/#/\$}}"; }, to make it quite small, as the question owner wishes. (Note, this is Bash-only solution. But anyway @Nobe4's function syntax is already a bashism.) – manatwork May 12 '16 at 12:09
2

Yes, that would probably have been a function, not an alias. With that in mind, try this:

pawk(){
    fields="$(sed -E 's/(^|,)/ \1\$/g'<<<"$1")"
    shift
    awk "{print $fields}" "$@"
}

Then you can run it as:

pawk 3,4,7 bigfile.txt | less

Or

cat bigfile | pawk 3,4,7 | less

Or even

pawk 3,4,7 * | less

The trick is adding a $ before each comma and at the beginning of the first argument given to the function (so 1,2,3 becomes $1,$2,$3) and and saving the resulting string in a shell variable. You then run awk in double quotes so that the $fields variable is expanded and awk treats it as the firlds it should print.

The sed -E should be pretty portable but, the herestring (<<<"$1") less so. For a fully portable version, use this:

pawk(){
    fields="$(printf '$%s' $(echo 1,2,3 | sed 's/,/,\$/g'))"
    shift
    awk "{print $fields}" "$@"
}
  • +1. and if you have shift after processing "$1" then you can use "$@" instead of just "$2". – cas May 12 '16 at 1:53

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.