Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: simple question on conditional expression
- X-seq: zsh-users 30376
- From: Stephane Chazelas <stephane@xxxxxxxxxxxx>
- To: Helmut Jarausch <jarausch@xxxxxxxxx>, zsh-users@xxxxxxx
- Subject: Re: simple question on conditional expression
- Date: Mon, 6 Oct 2025 21:42:14 +0100
- Archived-at: <https://zsh.org/users/30376>
- In-reply-to: <aOOgEYlURcYgePRg@eeyore.invalid>
- List-id: <zsh-users.zsh.org>
- Mail-followup-to: Helmut Jarausch <jarausch@xxxxxxxxx>, zsh-users@xxxxxxx
- References: <Z36OAOC3.QG24F7EC.YDGC5QCW@UOEOBWNG.T5YU5OXC.D3VB5HWZ> <aOOgEYlURcYgePRg@eeyore.invalid>
2025-10-06 12:55:13 +0200, Andreas Kähäri:
[...]
> > if ( echo $ANS | grep B ); then echo OK;fi
[...]
> The "if" statement uses the exit status of the command in parentheses to
> determine whether to execute the "then" block.
[...]
That's rather misleading. While there are shells such as (t)csh
or rc and derivatives where (...) is part of the "if" statement
syntax, that's not the case of zsh and other Bourne-like shells.
The Bourne syntax is:
if
cmdlistA
then
cmdlistB
else
cmdlistC
fi
Which runs cmdlistB if cmdlistA succeeds and cmdlistC otherwise.
(...) in Bourne-like shell is a compound command which is used
to run what's inside in a subshell environment. It's not related
in anyway to the "if" statement.
You do: (umask 077; cd /dir && cmd) for instance for the change
of umask and working directory to be done *only* in the subshell
prior to running cmd.
A (...) compound command exits with the exit status of the last
command run within, so ( echo $ANS | grep B ) will exit with the
exit status of grep, but the (...) to request a subshell
environment are unnecessary here.
A simple command often used in the cmdlistA part of an "if"
statement is the "[" command which can be used to perform a
number of simple tests. "grep" is also often used with the "-q"
(to not output the matching lines) and sometimes "-s" (to not
output any error) to look for matching lines in a file as in:
if
grep -qe "$regex" < $file
then
print -r "At least one line matching $regex was found in $file"
else
print No match
fi
Other *compound* commands commonly used as the condition part of
"if" statements are the ((...)) and [[...]] contructs from the
Korn shell, the former for C-like arithmetic expressions, the
latter for doing mostly the same as what the "[" command does
but using a specific microlanguage.
Here, to test whether a string contains another, you'd use the
latter:
if
[[ $ANS = *B* ]]
then
print -r -- "$ANS contains B"
fi
Or the POSIX equivalent:
case $ANS in
(*B*) printf '%s\n' "$ANS contains B"
esac
If you had to use grep, that would have to be:
if
echo -E - $ANS | grep -q B
then
print -r -- "$ANS contains B"
fi
(zsh-specific) or:
if
print -r -- "$ANS" | grep -q B
then
print -r -- "$ANS contains B"
fi
(Korn-shell compatible) or:
if
printf '%s\n' "$ANS" | grep -q B
then
printf '%s\n' "$ANS contains B"
fi
(POSIX). But I can't think of any reason why you would.
As an extra note, zsh has short forms of the if statement that
can be used if the last command in cmdlistA is a *compound
command* such as (( ... )), [[ ... ]] or (...)
if [[ $ANS = *B* ]] echo match
or:
if [[ $ANS = *B* ]] {print match} else {print no match}
So in the end you can have something looking similar to C:
if (( 3.1416 < 6.02e23 )) {
echo Avogadro beats Pi
}
Even more C-like than the C-shell where it would be:
if (1 < 2) then
echo ...
endif
--
Stephane
Messages sorted by:
Reverse Date,
Date,
Thread,
Author