【问题标题】:Case insensitive comparison in BashBash 中不区分大小写的比较
【发布时间】:2013-03-11 14:05:23
【问题描述】:

我正在尝试在不区分大小写的 while 语句中编写比较。基本上,我只是试图缩短以下内容,以便对用户提出是或否问题提示采取行动......

while[ $yn == "y" | $yn == "Y" | $yn == "Yes" | $yn == "yes" ] ; do

最好的方法是什么?

【问题讨论】:

标签: bash syntax


【解决方案1】:
shopt -s nocasematch
while [[ $yn == y || $yn == "yes" ]] ; do

或:

shopt -s nocasematch
while [[ $yn =~ (y|yes) ]] ; do

注意

  • [[ 是一个 bash 关键字,类似于(但比)[ 命令更强大。见http://mywiki.wooledge.org/BashFAQ/031http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
    除非您正在编写 POSIX sh,否则我们建议您使用 [[
  • [[=~ 运算符根据右手扩展正则表达式 (ERE) 评估左手字符串。成功匹配后,BASH_REMATCH 可用于扩展模式中的匹配组。正则表达式的引用部分变为文字。为了安全和兼容,将正则表达式放入参数中并执行[[ $string =~ $regex ]]

【讨论】:

  • shopt -s nocasematch 是否会导致我的基于 sed 的查找和替换也不区分大小写?
  • 试试吧,这将花费你 15 秒 =)
  • 对于正则表达式,最好使用^..$,例如yn="noyesno"
  • 我实际上希望所有字符都不区分大小写,但我认为只询问我指定的几个组合就足以从那里推断出来。你原来的while[[ $yn =~ (y|yes) ]] 似乎工作得很好。
  • [[ $yn =~ y(es)? ]];顺便说一句,(y|yes) 中的括号并不是真正需要的。
【解决方案2】:

也试试这个:

 [[ $yn =~ "^[yY](es)?$" ]] 

【讨论】:

  • 如果我也希望“es”不区分大小写,我可以输入 `[[ $yn =~ "^[yY][eE][sS]" || $yn == [yY] ]]?我希望能够接受“yEs”和“YeS”以及所有其他大小写组合。
  • @sputnick 看看这个问题和例子,只有y 不区分大小写,es 部分只是小写......我所理解的......
  • 如果您使用的是 Bash v4.x+,您可以在不调用 tr 的情况下执行字符串大小写转换。 yn=${yn,,}; [[ $yn =~ ^yes ]]
  • 在此处引用右侧实际上会抑制解释为正则表达式(Bash 3.1 和更早版本除外),因此这对于非古代 Bash 不起作用。安全的方法是在一个单独的变量中声明正则表达式,然后在 [[ ]] 中使用那个变量,不加引号。
【解决方案3】:

这是一个使用扩展模式而不是正则表达式的答案:

shopt -s nocasematch
shopt -s extglob
while [[ $yn = y?(es) ]]; do
  ...
done

请注意,从 4.1 版开始,bash 始终在 [[ ... ]] 条件表达式中使用扩展模式,因此不需要 shopt 行。

【讨论】:

  • 我认为你的'?在您的正则表达式中位于错误的位置。这将匹配“yes”或“es”,但不匹配“y”。
  • 不是正则表达式;这是一个扩展模式。 y 匹配自身; ?(es) 匹配零次或一次出现的模式 es
【解决方案4】:

无需使用 shopt 或正则表达式。最简单快捷的方法(只要你有 Bash 4):

if [ "${var1,,}" = "${var2,,}" ]; then
  echo "matched"
fi

您所做的只是将两个字符串都转换为小写并比较结果。

【讨论】:

  • 我刚刚尝试过,它奏效了。我不确定如何。您能否链接到文档或至少告诉该结构是如何命名的?
  • @AngeloFuchs ${my_variable,,} 语法是 bash 参数扩展。请参阅gnu.org/software/bash/manual/… 并滚动到该部分的底部以获取案例转换。
【解决方案5】:

我更喜欢使用grep -E 或简称egrep

while egrep -iq '^(y|yes)$' <<< $yn; do
  your_logic_here
done

这里有来自grep手册的解释:

-i, --ignore-case

忽略 PATTERN 和输入文件中的大小写区别。 (-i 由 POSIX 指定。)

-q, --quiet, --silent

安静;不要向标准输出写入任何内容。 如果发现任何匹配项,则立即以零状态退出,即使检测到错误也是如此。另请参阅 -s 或 --no-messages 选项。 (-q 由 POSIX 指定。)

【讨论】:

  • 这行得通,但使用 bash 内部语法比调用外部程序更有效。当然,对于交互式脚本来说,差异并不重要,因为循环中的人比外部进程慢几个数量级,但我仍然更喜欢在足够简单的情况下使用我的脚本语言自己的语法。
猜你喜欢
  • 2012-11-30
  • 1970-01-01
  • 2012-04-18
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多