Tuesday, January 18, 2011

using awk in a bash script with if

Hi,

I'm doing a script in which I need to test a string and based on its result I'll decide if I go further or not.

The command below works fine (if the string starts with "Clean" it will print 1, otherwise 0).

echo | awk ' {print index("'"${task}"'", "Clean")}'

What I'm trying to do is to use the AWK with IF in a BASH script. Based on this post I did the following:

idx=$(awk '{print index("'"${task}"'", "Clean")}')
echo $idx
if [ "$idx" == "0" ]; then
   echo hello
fi

As I said, when I run the script it prints "0", but the second "echo" doesn't print anything, and of course the if doesn't works either.

Can anyone help me?

TIA,

Bob

  • Awk is the wrong solution here. How about:

    if [[ "$task" =~ ^Clean ]]; then
      echo hello
    fi
    

    There's also a sneaky substitution method:

    if [ "${task/#Clean/}" != "$task" ]; then
      echo hello
    fi
    

    But I find that to be far less readable.


    Chris reckons case is tidier... let's try that out:

    case $task in
      Clean*)
        echo hello
        ;;
    esac
    

    My aesthetic sense says "hell no with bells on", and fiddling with the formatting (Clean*) echo hello;; or similar) won't help much, IMAO. If you want a conditional, use an if, I say.

    chris : You can use case for stuff like this; it's typically quite a bit tidier.
    chris : The nice thing about case statements is that they eliminate great big piles of if ; then ; elif ; then ; elif ; then ; else; fi structures, and they have better regular expression matching than test.
    womble : Well, when we get to having lots of if/elif blocks *involving the same variable*, we can switch to using a case statement. Also, case uses pathname expansion (roughly, globbing), whereas `[[ =~` uses *actual* regular expressions.
    From womble
  • Womble's answer is probably what I would go for, but you can also use grep:

    if echo cleanarf | grep -qi '^clean'; then 
       echo foo
    fi
    

    Drop the i switch to grep if you want it case sensitive (or if you do not want it case insensitive :-p ).

    womble : This is less readable, IMAO, and slower because it involves spawning a separate process.
    Kyle Brandt : Agreed, that is why I said I would opt for your answer :-P But options are good.
  • In your first example, you use echo to provide awk with a file (stdin), but in your script, there is no file for awk to process and it "hangs" waiting for input. You could use echo in your variable assignment in the $(), but I prefer to use /dev/null for this purpose (i.e. when there's no actual file to process).

    In order to avoid awkward quoting, you can use variable passing with the -v option to provide Bash variables to an awk script.

    You should find that this works:

    idx=$(awk -v task="$task" '{print index(task, "Clean")}' /dev/null)
    echo $idx
    if [ "$idx" == "0" ]; then
       echo hello
    fi
    

    You should probably use womble's suggestion, though, since it doesn't require spawning a separate process.

0 comments:

Post a Comment