POSIX documentation for pattern matching said that:
An ordinary character is a pattern that shall match itself. It can be any character in the supported character set except for NUL, those special shell characters in Quoting that require quoting, and the following three special pattern characters. Matching shall be based on the bit pattern used for encoding the character, not on the graphic representation of the character. If any character (ordinary, shell special, or pattern special) is quoted, that pattern shall match the character itself. The shell special characters always require quoting.
As I understand, the pattern ["!"a]
will match any of !
and a
. That's also the behavior in most shells I tried, except zsh
and ksh93
:
$ for shell in /bin/*[^c]sh; do
printf '=%-17s=\n' "$shell"
"$shell" -c 'case a in ["!"a]) echo 1;; esac'
done
=/bin/ash =
1
=/bin/bash =
1
=/bin/dash =
1
=/bin/heirloom-sh =
1
=/bin/ksh =
=/bin/lksh =
1
=/bin/mksh =
1
=/bin/pdksh =
1
=/bin/posh =
1
=/bin/schily-osh =
1
=/bin/schily-sh =
1
=/bin/yash =
1
=/bin/zsh =
zsh
and ksh93
seem to treat ["!"a]
the same as [!a]
, which match any character except a
:
$ for shell in ksh93 zsh; do
printf '=%-6s=\n' "$shell"
"$shell" -c 'case b in ["!"a]) echo 1;; esac'
done
=ksh93 =
1
=zsh =
1
Is there any reason (historical, development, ...) for zsh
and ksh93
behave like that?
zsh
does the same thing in both ksh
and sh
emulation.
busybox sh
, Solaris /usr/xpg4/bin/sh
and FreeBSD sh
also behave like POSIX documentation.
ksh88
also behave like most other shells, the behavior changed between kssh88
and ksh93
:
$ ksh88 -c 'case a in ["!a"]) echo yes; esac'
yes
$ ksh88 -c 'case b in ["a-c"]) echo yes; esac'
$
!
is matched, not the broader "any character except a".b
, not!
, it's copy-paste mistake.[]
recently in zsh, not enough it would seem. You may want to bring the discussion to the zsh mailing list. Check the archive of the ml.ksh
, it's the one actually surprise me a lot. I don't have ksh88 for testing. But I guess it will be compliant. Can you help me checking it?