Case 语句只允许字母字符?

Case 语句只允许字母字符?
case "$1" in
all)
  echo "$1"
  ;;
[a-z][a-z][a-z][a-z][a-z][a-z])
  echo "$1"
  ;;
*)
  printf 'Invalid: %s\n' "$3"
  exit 1
  ;;
esac

在此情况下,唯一接受的输入是全部 6 个字符。它不接受 4 个字符或超过 6 个字符。

我在这里想做的是只允许字符,而不是数字或符号,但长度不受限制。

正确的语法是什么?谢谢

答案1

数字或者符号是字符。看起来您想要:

  1. 仅限字母字符 ( [[:alpha:]])
  2. 或可能是字母字符,但仅限拉丁文字(如您的a-z建议)
  3. 或者可能是拉丁字母中的字母字符,并且没有变音符号。

除非语言环境是 C/POSIX,否则[a-z]匹配或多或少是随机的bash(至少在 GNU 系统上)。

对于 1,您需要:

die() {
  printf >&2 '%s\n' "$1"
  exit 1
}
case $string in
  ("") die "Can't be empty";;
  (*[![:alpha:]]*) die "contains non-alphabetical characters";;
  (*) echo OK
esac

这将接受all, Stéphane(拉丁字母)、γράμμα(希腊字母)、письмо(西里尔字母),但不接受foo-bar, 123...

2 可能很棘手,特别是当您想考虑组合变音符号时。

对于 3,为了让它在任何区域设置中运行,您需要指定所需的字符:

ok=abcdefghijklmnopqstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

并在case声明中使用

(*[!$ok]*) die "contains characters not allowed";;

或者您可以切换到基于字符代码点zsh的范围,因此始终仅包含 abcdefghijklmnopqstuvwxyz 或使用 bash 4.3 或更高版本[a-zA-Z]使用该globasciiranges选项具有相同的行为bash

答案2

您可以使用标准模式匹配来执行此操作,方法是查找任何不允许的字符,并在找到任何字符时拒绝输入。或者你可以使用扩展的全局( extglob) 或正则表达式,并明确确保整个字符串由以下字符组成允许。

#/bin/bash
shopt -s extglob globasciiranges
case "$1" in *([a-zA-Z]))    echo "case ok" ;; esac
[[ "$1" = *([a-zA-Z]) ]]  && echo " [[  ok"
[[ "$1" =~ ^[a-zA-Z]*$ ]] && echo "rege ok"

globasciiranges阻止[a-z]匹配重音字母,但正则表达式匹配不遵守它。使用正则表达式,您需要进行设置LC_COLLATE=C以防止匹配它们。

所有这些都允许空字符串。为了防止这种情况,请将星号更改为加号 (*+)。

答案3

如果您正在使用bash或等效项,请在脚本顶部包含该行set -s extglob以启用扩展通配(正则表达式的一种形式),然后在语句中将case选择器设置为+([[:alpha:]]),当然后面跟着语句本身)所需的内容case

alpha是几个之一字符类手册页中定义bash。它包含您所在区域的所有字母字符(大写和小写)。

相关内容