(of course we could just @code{unset} @code{CDPATH}, it also behaves
properly if set to the empty string).
-Life wouldn't be so much fun if @command{bash} abd @command{zsh} had the
+Life wouldn't be so much fun if @command{bash} and @command{zsh} had the
same behavior:
@example
OK
@end example
+@item @command{echo}
+@cindex @command{echo}
+The simple @code{echo} is probably the most surprising source of
+portability troubles.
+
+Don't expect any option. @xref{Preset Output Variables}, @code{ECHO_N}
+etc. for a means to simulate @samp{-c}.
+
+Do not use backslashes in the arguments, as there is no consensus on
+their handling:
+
+On @samp{foo='\n'; echo "$foo" | wc -l}, the @command{sh} of Digital
+Unix 4.0, RISC/os 4.52, answer 2, but the Solaris' @command{sh}, Bash
+and Zsh (in @command{sh} emulation mode) report 1.
+
@item @command{exit}
@cindex @command{exit}
Some shell scripts, such as those generated by @command{autoconf}, use a
@example
case $ac_feature in
- *[^-a-zA-Z0-9_]*) @var{action};;
+ *[!-a-zA-Z0-9_]*) @var{action};;
esac
@end example
-Alas, negated character classes are not portable (some old shells
-support the @samp{[!...]} syntax, some modern shells such as
-@command{zsh} support only the more recent syntax @samp{[^...]}). One
-solution can be:
+Alas, negated character classes are probably not portable, although no
+shell is known not to support the @sc{posix.2} syntax @samp{[!...]}
+(when in interactive mode, @command{zsh} is confused by the
+@samp{[!...]} syntax and looks for an event in its history because of
+@samp{!}). Many shell do not support the alternative syntax
+@samp{[^...]} (Solaris, Digital Unix etc.).
+
+One solution can be:
@example
-expr "$ac_feature" : ".*[^-a-zA-Z0-9_]" >/dev/null &&
+expr "$ac_feature" : '.*[^-a-zA-Z0-9_]' >/dev/null &&
@var{action}
@end example
or better yet
@example
-expr "x$ac_feature" : ".*[^-a-zA-Z0-9_]" >/dev/null &&
+expr "x$ac_feature" : '.*[^-a-zA-Z0-9_]' >/dev/null &&
@var{action}
@end example
-It is somewhat more robust than the @samp{echo | grep} solution which
-suffers the limitations of @command{echo}: its argument should be too
-special (containing backslashes).
+@samp{expr "X@var{foo}" : "X@var{bar}"} is more robust than @samp{echo
+"X@var{foo}" | grep "^X@var{bar}"}, because it avoids problems when
+@samp{@var{foo}} contains backslashes.
@item @command{unset}
@item @command{expr}
@cindex @command{expr}
-Don't use @samp{\?}, @samp{\+} and @samp{\|} which are not supported by
-Solaris.
+Don't use @samp{\?}, @samp{\+} and @samp{\|} in patterns, they are
+not supported on Solaris.
+
+No @command{expr} keyword starts with @samp{x}, so use @samp{expr
+x"@var{word}" : '@var{regex}'} to keep @command{expr} from
+misinterpreting @var{word}.
-There is no known command of @command{expr} starting with @samp{x}, so
-using @samp{expr x"@var{word}" : '@var{regex}'} avoids problems if
-@var{word} happens to have a meaning for @command{expr}.
+Don't use @code{length}, @code{substr}, @code{match} and @code{index}.
@item @command{grep}
@cindex @command{grep}
@code{sed} have an input buffer limited to 4000 bytes.
Alternation, @samp{\|}, is common but not portable.
+
+Nested groups are extremely portable, but there is at least one sed
+(System V/68 Base Operating System R3V7.1) which does not support it.
@end table