【问题标题】:Make the if statement case insensitive in bash在 bash 中使 if 语句不区分大小写
【发布时间】:2021-05-21 18:18:02
【问题描述】:

我的代码将使用 curl 检查标题。有时标头及其值以大写字母显示,有时以小写字母显示。

例如X-Requested-Id 可以找到x-requested-id 或X-Requested-ID。

如何使 if 语句不区分大小写?

if [[ $check_headers == "X-Requested-Id"* ]]; then

【问题讨论】:

  • 试试shopt -s nocasematch
  • 请注意,设置 nocasematch 也会影响其他类型的模式匹配,前提是它们由 shell 完成(例如文件名通配符和 [[ string =~ regex ]],但不是 匹配由grep、sed 等完成)。你可能想要也可能不想要这个,所以准备好根据需要打开和关闭nocasematch。

标签: bash curl header case-insensitive lowercase


【解决方案1】:

使用 Bash 4 或更高版本,您可以使用 parameter expansion 将字符串小写:

if [[ ${check_headers,,} == "x-requested-id"* ]]; then

【讨论】:

  • @sof31 确保右侧也是小写。
  • @sof31;如果您(仍然)在获得此答案时遇到问题,请考虑提出一个新问题并提供详细信息,以便我们重现该问题
  • @markp-fuso 问题解决了。正如格伦杰克曼所说,我需要将 if 语句的右侧设为小写。谢谢。
【解决方案2】:

如果您无法访问 Bash 4(或更高版本),您可以将单独的变量定义为小写,然后根据需要引用“小写”变量,例如:

$ myvar='ABC_def'
$ typeset -l myvar_lower="${myvar}"
$ echo "${myvar_lower}"
abc_def

返回 OP 问题:

typeset -l check_headers_lower="${check_headers}"

if [[ "${check_headers_lower}" == "X-Requested-Id"* ]]; then

注意事项:

  • 没有什么可以阻止您将原始变量定义为小写,只要您确定原始大小写的数据不会有后续要求
  • 改变变量的大小写不会影响变量的当前值; a) x=A; typeset -l x; echo "${x}" => A b) typeset -l x; x=A; echo "${x}" => a c) typeset -l x=A; echo "${x}" => @987654328 @ d) x=A; typeset -l x="${x}"; echo "${x}" => a

【讨论】:

    【解决方案3】:

    使用nocasematch shell 选项。就像在 cmets 中提到的 Gordon Davisson 一样,它应该在测试后禁用,并注意其他模式匹配,例如使用 =~ 运算符。

    shopt -s nocasematch
    if [[ $check_headers == "X-Requested-Id"* ]]; then
     ...
    fi
    shopt -u nocasematch
    

    就像@Benjamin W. 在评论中提到的那样,最好先检查值shopt 的状态。

    使用eval

    oldvalue=$(shopt -p nocasematch)
    shopt -s nocasematch
    
    if [[ $check_headers == "X-Requested-Id"* ]]; then
         ...
    fi
    
    eval "$oldvalue"
    

    我会在启用之前先检查shopt 的状态,然后再禁用它。

    没有eval,类似这样

    #!/usr/bin/env bash
    
    if ! shopt -q nocasematch; then
      shopt -s nocasematch
      on=1
    fi
    
    if [[ $check_headers == "X-Requested-Id"* ]]; then
      ....
    fi
    
    if ((on)); then 
      shopt -u nocasematch
      on=0
    fi
    

    【讨论】:

    • 提防其他模式匹配,例如使用 =~ 运算符。 是什么意思?如果我在 shopt 中使用 =~ 或 == 会有什么区别?
    • =~ 与正则表达式匹配,如果启用了nocasematch,那么它可能会产生一些无意的结果。
    • 如果您不想盲目地打开和关闭,而是想确保将选项设置为之前的值,您可以执行类似oldvalue=$(shopt -p nocasematch); shopt -s nocasematch 和稍后的eval "$oldvalue" 之类的操作。
    • @BenjaminW。感谢您的评论。相应地更新了我的答案。
    【解决方案4】:

    我更喜欢这里已经提出的所有其他建议,但是...

    如果,在紧要关头,您不记得那些语法,并且由于某种原因没有时间查找它们,请记住 if 只是检查其操作数的返回值,所以你总是可以使用另一个程序。 (哎呀,我讨厌运行不必要的进程,但正如我所说,这是一个要记住的黑客......)

    if grep -i x-requested-id <<< "$check_headers" # grep -i is case-insensitive
    

    编辑

    要详细说明 Benjamin 的解决方案,我认为它非常好,试试这个:

    $: [[ X == x ]] && echo ok || echo no # case sensitive, fails
    no
    $: ( shopt -s nocasematch; [[ X == x ]] && echo ok || echo no; ) # in a subshell
    ok
    $: [[ X == x ]] && echo ok || echo no # back to normal
    no
    

    将其包装在子 shell 中会限制 nocasematch 的范围。

    您说他的解决方案“不起作用”。能详细点吗?

    【讨论】:

    • 工作正常,但正在寻找更轻的解决方案以避免更多进程。本杰明的解决方案似乎很容易使用,但它对我不起作用,但我有 bash 版本 5。有什么想法吗?
    • 现在可以使用了。问题是我没有用小写写 if 语句的右侧。
    猜你喜欢
    • 1970-01-01
    • 2013-09-04
    • 2020-09-23
    • 2014-09-25
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多