AWK Script and Commandline difference

Hey there,

I just stumbled upon a difference between using awk on the commandline and using it in a shellscript.

I have a variable, e.g.: PROG=vim
then i want to check if the package with this name is installed: TEMPVAL=$(dpkg -l | awk '{ if ($2 == "$PROG") print $2 }') (Im using Tempval later in an condition to check if it is installed)
Running this on the commandline works fine. In the shellscript TEMPVAL is always empty.

btw "toinstall" just contains some package names to be installed and comments prefixed with #

full script:

#!/bin/bash

for prog in `cat toinstall | grep -vP "^#" | grep -vP "^$"`
do
    TEMPVAL=$(`dpkg -l | awk '{ if ($2 == "${prog}") print $2}'`)
    if [  "$TEMPVAL" == "" ]
    then
    sudo apt-get install -y $prog
    fi
done

bash -x output:

+ for prog in '`cat toinstall | grep -vP "^#" | grep -vP "^$"`'
+++ dpkg -l
+++ awk '{ if ($2 == "${prog}") print $2}'
+ TEMPVAL=
+ '[' '' == '' ']'
+ sudo apt-get install -y vim

Whats the Problem?:wall: I already tried playing with the quotation, but nothing worked. Hope somebody can help me. I'd also appreciate hints or tips if theres a more convenient way of doing what i want to do :b:

Greetings, MrSnail

TEMPVAL=$(dpkg -l | awk '{ if ($2 == "'${prog}'") print $2}')

Or (my prefred way):

TEMPVAL=$(dpkg -l | awk '{ if ($2 == prog) print $2}' prog="${prog}")

Jean-Pierre.

awk '{ if ($2 == "'"$prog"'") print $2}'

This article describes three ways to interface AWK programs with shell scripts and how to import shell variables into AWK programs.

But a little better:

awk '$2 == "'"$prog"'" {print $2}'

The inner double quotes are really not needed here but this is a good habit.

Well,... that was quite easy :smiley:
Thanks a lot for this fast response. :slight_smile:

It's actually a pretty bad habit -- there's a much better way to get variables into awk, -v. No need to mess with ending and beginning single and double quotes inside the awk script itself.

awk -v VAR="$prog" '$2 == VAR { print $2 }'

I wrote about quoting shell variables not about embedding.

Maybe you true about awk but the "pretty bad" way is universal - it's for perl, sed, python or almost anything other, where you want to embed shell variables.

It's a bad idea because it becomes language syntax, not merely a string. This is especially bad for a variable, where you might not have strict control over the exact contents:

$ STR="hello 'world'"
$ awk 'BEGIN { print "'$STR'" }'
awk: BEGIN { print "hello
awk:               ^ unterminated string
$
 VAR="this will barf'"
# subsitute in the shell and it barfs, taking the extra ' as perl syntax
$ perl -e "print '$VAR', "\n";'
Can't find string terminator '"' anywhere before EOF at -e line 1.
# do it properly and it will not.
$ perl -e 'print shift, "\n"' "$VAR"
this will barf'
$

I admit there's no good way to do it in sed, but this is an argument against sed, not an argument for that syntax. It's very difficult to safely put variables in sed because so many things need escaping.

And if the argument is that you don't need to memorize syntax for each language, well, you already had to memorize -e for perl, how much harder is -v, shift, etc?

But i wrote exactly about this! Put shell variables inside double quotes:

$ STR="hello 'world'"
app@kf3sv ~
$ awk 'BEGIN { print "'"$STR"'" }'
hello 'world'
$ perl -e 'print "'"$VAR"'", "\n";'
this will barf'

And yes - threre is not an universal "safe" way to embed shell variables. But I believe there is not any universal way to write "safe" shell scripts. Shell is a command language, you know - for those who write and execute commands.

And I repeat one more:
The inner double quotes are really not needed here but this is a good habit.

Okay, how about:

$ STR="hello \"world\""
$ awk 'BEGIN { print "'"$STR"'" }'
hello
$ STR='"; system("/sbin/poweroff") ; print "'
$ awk 'BEGIN { print "'"$STR"'" }'

poweroff: must be superuser.

$ awk -v VAR="$STR" 'BEGIN { print VAR }'
"; system("/sbin/poweroff") ; print "
$

Extra quotes don't protect you no matter how many of them you have. They do leave you wide open to bizzare errors and intentional abuse. The -v syntax eliminates all these problems.

Your method isn't merely imperfect, it's downright unsafe.

Well, enough. Just only - it is not my method - it's common practice to embed shell variables in perl, sed, sql etc.

If it really is "common practice" that's alarming.

I don't understand your defensiveness. There may be situations where substituting strings into the program text itself is the only option(I already demonstrated how to avoid that in perl with shift), but this topic, about awk, isn't one of them.