I am trying to use awk inside a shell script function, but can't seem to find a reference that tells me how to properly escape the awk variable ($4). Inside the function it keeps getting replaced at the 4th item passed to the function (Null).

    fileID=$(cat qkViews/${dir}iHealth-Files.json|grep -B5 '${1}'|grep id|awk '{print $4}'|sed 's/,//g; s/\"//g')
    echo $fileID
    echo "Retrieving file $1 as $fileID from ID: $ID"

(disclaimer: Yes, I could probably do something differently with the piped commands... but my main goal is to figure out the escaping of the $4 first.)

  • 3
    awk '{print $4}' is the correct way to return the fourth field. You have put $4 in single-quotes which is the correct way to protect it from the shell. The error is caused by something else. Provide details and maybe we can help. – John1024 Dec 10 '17 at 22:58
  • @john1024, changing $4 in the awk script portion to '$4' still doesn't prevent the $4 from being evaluated as a parameter to the function, unfortunately. – Jerry Lees Dec 11 '17 at 3:45
  • The way that you have it in the question, awk '{print $4}', is correct if you are expecting awk to evaluate $4 as the fourth field on the input line. The single quotes prevent the shell from altering the command before awk is run. – John1024 Dec 11 '17 at 3:51
  • Did @roaima's answer work for? If not, you need to make more clear what your input looks like and what output you expect. – John1024 Dec 11 '17 at 3:52

As far as I can tell without any contextual data, the error is not in your awk code, but within your first grep, which is looking for the literal four characters ${1}. I suspect this was intended to be the first parameter passed to your function.

I've altered your code a little. If you really intended the echo $fileID to remove extraneous whitespace you'll want to remove the double quotes I've added around the variable there.

You're also using a couple of global variables. Mixing local variables ($1) and global variables ($dir and $ID) is not particularly good coding practice, but there are times in a script where pragamatism may need to win.

        grep -B5 "$1" "qkViews/${dir}iHealth-Files.json" |
        awk '/id/ {print $4}'|
        tr -d ',"'
    echo "$fileID"
    echo "Retrieving file $1 as $fileID from ID: $ID"
  • The $1 is correct, it's the filename passed to the function. The function is called like so, "iHealthGetFile /some/directory/some/FileName" In this case, like any shell script function, $1 represents the first parameter passed when the function is called. This is desirable. However, the replacement of $4 in the awk command is not since it is not intended to be the fourth parameter passed, but instead part of the awk function. – Jerry Lees Dec 11 '17 at 0:09
  • 1
    @JerryLees great; I've understood what your code is trying to do. The problem was in the first grep statement. There is nothing wrong with your awk statement as presented in your question – roaima Dec 11 '17 at 8:24

In your question you claim that awk returns null as a result of $4 passed to the shell function is null.

The reason that your awk (or your whole pipe) returns null is not due to a kind of confussion with shell function parameters.
It is just because whatever is feeding awk with data (left part of your awk pipe) has not a valid 4th field .

This test will prove it:

$ function tt { echo "1:$1-2:$2-3:$3-4:$4"; echo "first second third fourth" |awk '{print $4}'; }
$ tt one two #call the function with only two parameters. 3 and 4 are null
1:one-2:two-3:-4: #Parameters passed to function
fourth #awk result

As you can see , awk result is not affected by function parameters . If the data provided to awk are valid, 4th field of these data will be returned.

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.