0

when the below code is execute if is detected on my pc but when i execute the same command on office pc if is not getting detected what could be possible reason for this ambiguous behavior

$p is one line of text file , xyzxyz if ( abc ) i am using while read to pass line to grep

grep -qw -e 'if(' -e 'if' <<< $p
if [ $? -ne 0 ]; then

do something

fi
  • What OS does your home and office PC run? – Hunter.S.Thompson Sep 20 '17 at 18:58
  • my home pc has linux mint and on office pc , i am using VMplayer running RHEL 6 – user143252 Sep 20 '17 at 18:59
  • if $p is a file, use < (only one <) rather than (three <<< ) – Archemar Sep 20 '17 at 19:00
  • its one line of text file , just like export p='xyzxyz if ( abc )' – user143252 Sep 20 '17 at 19:03
  • 1
    And also, what is the output of grep -ow -e 'if(' -e 'if' <<< $p on both systems? (note the -o). It should be just if I think. – Kusalananda Sep 20 '17 at 19:39
4

Older versions of bash had that bug/misfeature in that in

 cat <<< $var

The content of $var would undergo word splitting (but not globbing) and the resulting words joined with spaces before being put in a temporary file set as input to the cat command.

That was fixed in bash-4.4 to align with the other shells supporting that <<< zsh operator.

For older versions, that's another case where you need to quote your variables.

So if $IFS contained i or f, that could explain the discrepancy:

$ a='if' bash4.1 -c 'IFS=f; cat <<< $a'
i
$ a='if' bash4.4 -c 'IFS=f; cat <<< $a'
if

In any case, note that the -e 'if(' is redundant since if a text contains if( as a word, it also contains a if word.

Also note that bash has regexp matching built-in, so you can always do

re='\<if\>'
if [[ $p =~ $re ]]; then
  printf '"%s" contains a "if" word\n' "$p"
fi

(at least on systems like Linux Mint and RHEL where EREs have those \<, \>, but if your grep supports -w, it's likely EREs will have \< and \> as well).

(above is one of those very rare cases where $p doesn't need to be quoted (though quoting won't harm), and $re must not be quoted (otherwise its content is not taken as a regular expression, but as a fixed string))

With standard sh syntax, you can also do:

case +$p+ in
  (*[^[:alnum:]_]if[^[:alnum:]_]*)
    printf '"%s" contains a "if" word\n' "$p"
esac

To get the same effect.

Not the answer you're looking for? Browse other questions tagged or ask your own question.