2

I'm trying to access a command line argument within the function below but I can't get it to work. I believe it has something to do with the quotes but I can't figure it out.

search_second_line() {
    awk 'FNR==2 {if (/$1)/) print FILENAME; nextfile}' ./*
}
alias st="search_second_line"
chishaku
  • 4,577
  • 3
  • 25
  • 33

1 Answers1

5

This will work (but you have to be careful what you use for an argument):

st() { awk "FNR==2 {if (/$1/) print FILENAME; nextfile}" ./*; }

The danger here is that $1 becomes part of the code and, if it includes awk-active characters, could do surprising things.

This is a bit safer:

st() { awk -v c="$1" 'FNR==2 {if ($0 ~ c) print FILENAME; nextfile}' ./*; }

Here, we pass into awk a variable c that has the contents of $1. awk will know to treat c as a variable, not as code.

This is the same as the above but it simplifies the logic:

st() { awk -v c="$1" 'FNR==2 && $0~c {print FILENAME; nextfile}' ./*; }

How it works

  • -v c="$1"

    This defines awk variable c. This is the most reliable to pass information from the shell to awk.

  • FNR==2 && $0~c {print FILENAME; nextfile}

    This applies two conditions and'd together before the print/nextfile statement is executed. The first requires that this be the second line. The second requires that this line match c.

The shell and quoting

The difference between single and double quotes is easily demonstrated at the command line. Try:

$ var="Hello"
$ echo '$var'
$var
$ echo "$var"
Hello

As shown above, the shell treats the contents of single-quotes literally. It makes no changes to what is inside single-quotes. By contrast, the shell will process the contents of double-quotes, doing variable substitution (shown above), as well as command substitution and arithmetic expansion. To demonstrate the latter two:

$ echo '$var $(date) $((2*3))'
$var $(date) $((2*3))
$ echo "$var $(date) $((2*3))"
Hello Wed Nov 19 14:15:44 PST 2014 6
John1024
  • 109,961
  • 14
  • 137
  • 171
  • I'd suggest `printf '%q\n'` rather than `echo` for your demonstrations -- that way the effects of string-splitting will be obvious, too, distinguishing `printf '%q\n' $var $(date) $((2*3))` from `printf '%q\n' "$var" "$(date)" $((2*3))`. – Charles Duffy Nov 19 '14 at 22:23