Negating shell interpretation

I'm writing a Korn script but am having trouble because the shell interprets the asterisk in this case. Can anyone tell me if there is a way to fix this so that grep takes in STDIN without the interpretation?

line="30 09 * * 1-4 /home/user01/bin/start"
echo "$line" | grep 'start'

I am not sure what you mean. With the example that you provided, the shell will not interpret the asterisks.

You are correct .. I thought I typed those in manually in to the shell and tested it ... How about this? It's more of what the script looks like:

#!/bin/ksh

line="01 01 * * 5 /home/user01/bin/start"

if [ $( echo "$line" | grep 'start' ) ]
then
  start="$final"
fi

print $start

It fails at the if statement.

Try this...

#!/bin/ksh

line="01 01 * * 5 /home/user01/bin/start"

if  grep -q 'start' <<<$line
then
  start="$final"
fi

echo $start

Hope somewhere you have final populated!

--ahamed

Sorry, $final is populated somewhere in the script ... In the following script, I modified it so that it just uses $line instead.

$ cat g.ksh
#!/bin/ksh

line="01 01 * * 5 /home/user01/bin/start"

if  grep -q 'start' <<<$line
then
  start="$line"
fi

echo $start

$ ./g.ksh
./g.ksh[5]: syntax error at line 5 : `<' unexpected

change the <<< to << 2 "<" characters not 3

if  echo "$line" | grep -q 'start'
then
  start="final"
fi

--ahamed

Try:

#!/bin/ksh

final="test bla bla"
line="01 01 * * 5 /home/user01/bin/start"

if echo "$line" | grep 'start' >/dev/null 2>&1
then
  start="$final"
fi

echo "$start"

Or without external programs...

#!/bin/ksh

final="test bla bla"
line="01 01 * * 5 /home/user01/bin/start"

case $line in
  *start*) start="$final"
esac

echo "$start"

Why use grep at all? Take advantage of Kshell's pattern matching:

#!/usr/bin/env ksh

final="test bla bla"
line="01 01 * * 5 /home/user01/bin/start"

if [[ $line == *"start"* ]]
then
  start="$final"
fi

Depending on how this is being used, and thus the number of grep processes that are avoided, this is much more efficient.

1 Like

Why limit it to ksh? Scrutinizer's case statement (which also avoids external commands) will work in all Bourne-type shells.

1 Like

Right. I missed the case example and specifically mentioned kshell because the original post indicated kshell was being used.

Hey guys,

Thanks for all the input so far. It's been really helpful. It looks like this line is working currently:

if [[ $line == *"start"* ]]

In this following snippet, line 9 only needs one set of square brackets but lines 13 and 16 needs two set of square brackets. Any thoughts?

     8	function match {
     9	    temp=$( echo "$line" | egrep '(start|stop)' )
    10	    
    11	    if [ ! -z "$temp" ]
    12	    then
    13		if [[ $( echo "$temp" | grep 'start') ]]
    14		then
    15		    start="$temp"
    16		elif  [[ $( echo "$temp" | grep 'stop') ]]
    17		then
    18		    end="$temp"
    19		fi
    20	    fi
    21	}

The open square bracket [ is a symbolic link to the test command and gives the appearance of wrapping the expression in parenthesis-like format that most programmers are used to. The double bracket, is a part of the shell syntax.

The expression that appears between single brackets is given to the test command while the expression inside of double brackets is interpreted by the shell. The shell interpretation supports the evaluation of the command exit code like you want to do, while the test command does not and that is why you need the double brackets where you've discovered that you do.

In my humble opinion, there is rarely a case where single brackets (the test command) are needed; using double bracketed expressions is much more efficient especially when loops are involved.

You don't need grep, and you don't need double (or single) brackets.

Use case:

match() {
  case $line in
    *start*) start=$line ;;
    *stop*)  end=$line ;;
  esac
}

---------- Post updated at 06:12 PM ---------- Previous update was at 06:06 PM ----------

The open square bracket [ is a shell builtin command, and it is synonymous with test :

$ type test [   
test is a shell builtin
[ is a shell builtin

IMNSHO, there is rarely a case where double brackets are needed (I never use them).

The double brackets are not part of the POSIX definition of the shell, and thus are less portable.

This I didn't realise, mostly because /usr/bin/[ seems to persist everywhere. Wrongly, I assumed it still then required a fork/exec to use it. Thanks for the correction.

POSIX requires that regular built-in commands also exist as separate binaries.

Indeed. One of the reasons why [/usr]/bin/cd is available in POSIX compliant OSes.