混合数字和字母的 Bash 大小写匹配问题

混合数字和字母的 Bash 大小写匹配问题

我正在尝试允许用户输入将要使用的尺寸fallocate,因此我需要确保输入的文本为 1G、8G、512M 等。

我有下面的代码;但是,所有正确的格式都转到默认*情况。

echo -n "What amount do you want to allocate to the new swapfile? [i.e. 4G or 512M]\n"
read size
echo $size
case $size in

    [1-9][0-9]*[m|M|g|G] )
        echo "Size Verified: $size"
        ;;

    *) 
        echo "Invalid size: $size. Please use the format 1-999[M|G]. 
        ;;
esac

我已经检查过我的正则表达式https://regexr.com/使用以下([1-9][0-9]*[m|M|g|G])

注意:我知道我的警告信息比我的正则表达式更严格。另外,我对 bash 还很陌生。如果技术先进,请提供额外的链接,以便我可以研究。

答案1

首先,case使用 shell 通配符 - 它与正则表达式不同。特别是,*(和?) 本身就是通配符匹配,而不是影响前一个原子的量词。例如:

  • 基本正则表达式:

    [0-9]? means 0 or 1 decimal digit
    [0-9]* means 0 or more decimal digits
    
  • 简单的全局变量

    [0-9]? means a decimal digit followed by any single character
    [0-9]* means a decimal digit followed by any number of characters (including none)
    

据我所知,没有办法在简单的 shell glob 中指定任意数量的重复。您有多种选择:

  1. 使用简单的 shell glob,明确匹配每个序列并将它们或在一起。例如,对于 1-3 位数字,

    case $1 in
      [0-9][mMgG]|[0-9][0-9][mMgG]|[0-9][0-9][0-9][mMgG])
        echo "simple glob match"
      ;;
      *)
        echo "no simple glob match"
      ;;
    esac
    
  2. 使用 bash扩展的 glob,可以是[0-9]*([0-9])(一位数字后跟零个或多个数字 - 类似于正则表达式)或+([0-9])(一位或多位数字)。请注意,与正则表达式不同,量词位于原子之前,而不是之后

    shopt -s extglob
    
    case $1 in
      +([0-9])[mMgG])
        echo "extended glob match"
      ;;
      *)
        echo "no extended glob match"
      ;;
    esac
    
  3. 使用 bash 正则表达式,但在if...then条件内

    if [[ $1 =~ [0-9][0-9]*[mMgG] ]]; then
      echo "regex match"
    else
      echo "no regex match"
    fi
    

在最后一种情况下,您还可以使用短路逻辑:

[[ $1 =~ [0-9][0-9]*[mMgG] ]] && echo "regex match" || echo "no regex match"

还要注意,在 glob 和正则表达式中,[...]都是一组字符而不是表达式,因此与文字字符、、和[m|M|g|G]没有什么不同,并且匹配(可能不是您想要的)。[mMgG|]mMgG|

相关内容