AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 432660
Accepted
siery
siery
Asked: 2018-03-22 11:21:00 +0800 CST2018-03-22 11:21:00 +0800 CST 2018-03-22 11:21:00 +0800 CST

在 case 语句中将数字与正则表达式匹配

  • 772

我想检查 shell 脚本的参数是否是整数(即非负整数:0、1、2、3、...、17、...、42、...等,但不是 3.1416 或 -5 ) 以十进制表示(所以没有 0x11 或 0x2A 之类的)。如何使用正则表达式作为条件(匹配数字)编写 case 语句?我尝试了几种不同的方法(例如,[0-9]+或^[0-9][0-9]*$);它们都不起作用。就像在下面的示例中一样,有效数字正在通过旨在捕获它们并匹配 *通配符的数字正则表达式。

i=1
let arg_n=$#+1

while (( $i < $arg_n )); do
    case ${!i} in
    [0-9]+)
        n=${!i}
        ;;
    *)
        echo 'Invalid argument!'
        ;;
    esac
    let i=$i+1
done

输出:

$ ./cmd.sh 64
Invalid argument!
bash regular-expression
  • 3 3 个回答
  • 18728 Views

3 个回答

  • Voted
  1. Best Answer
    glenn jackman
    2018-03-22T11:41:06+08:002018-03-22T11:41:06+08:00

    case不使用正则表达式,它使用模式

    对于“1 个或多个数字”,请执行以下操作:

    shopt -s extglob
    ...
        case ${!i} in
            +([[:digit:]]) )
                n=${!i}
                ;;
        ...
    

    如果要使用正则表达式,请使用其中的=~运算符[[...]]

    if [[ ${!i} =~ ^[[:digit:]]+$ ]]; then
        n=${!i}
    else
        echo "Invalid"
    fi
    
    • 11
  2. G-Man Says 'Reinstate Monica'
    2018-03-22T21:09:37+08:002018-03-22T21:09:37+08:00

    正如 glenn 所说,“case不使用正则表达式,它使用模式”。正如bash(1)所说,

    case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

          一个case命令首先扩展word,然后尝试pattern依次将其与每个命令进行匹配,使用与路径名扩展相同的匹配规则(请参阅下面的路径名扩展)。

    同样,POSIX 规范说,

    ... 每个模式... 应与word的扩展进行比较,根据Pattern Matching Notation中描述的规则 ...

    所以这些模式是路径名扩展模式,又名通配符,又名 glob,如ls -l -- *.shor rm -- *.bak。

    当然,shopt -s extglob并且[[ … =~ … ]] 是自切片面包以来最整洁的东西,但它们不是 POSIX,知道如何使用原始工具会很有用。多年来,例如,程序员通过检查字符串是否不是数字来检查字符串是否为数字。您已将数字定义为(完全)由一个或多个数字组成的字符串。因此,如果字符串为空或包含非数字字符,则字符串不是数字。case我们可以使用如下语句来测试这些条件:

    case "$1" in
        ("")
            # null
               ︙
            ;;
        (*[!0-9]*)
            # contains non-numeric character(s)
               ︙
            ;;
        (*)
            # is a whole number (non-negative integer)
               ︙
    esac
    

    where[!0-9]是老式的 shell 说法[^0-9],当然,它表示除数字之外的任何字符。([!…]并且[^…]两者都在 bash.  [!…]中工作,POSIX 要求工作;结果[^…]未指定。)如果您不关心字符串是哪种非数字,您可以组合非数字模式:

    case "$1" in
        ("" | *[!0-9]*)
            # not a number
               ︙
            ;;
        (*)
            # is a number
               ︙
    esac
    

    作为练习,这里有一个case处理任何类型实数的语句 - 准确地说,是一个或多个数字的字符串,在某处可选带句点 ( ),开头.可选带减号 ( )。-

    case "$1" in
        (*[!-.0-9]*)
            # contains non-numeric character(s)
            ;;
        (*?-*)
            # contains '-' somewhere other than the first position
            ;;
        (*.*.*)
            # contains multiple decimal points
            ;;
        (*)
            case "$1" in
                (*[0-9]*)
                    # is a real number
                    ;;
                (*)
                    # not a number
            esac
    esac
    

    我添加了case-within-a-case来验证字符串确实包含至少一个数字。在整数示例中这不是必需的,因为我测试了字符串是否为空;我已从该声明中删除的测试。没有第二个case,一个-或一个.——甚至-.——将有资格作为一个数字。当然,我们可以添加模式来处理这些异常,但这会变得复杂。(例如,我几乎发布了这个答案,却没有意识到这-.是例外之一。)我相信上述方法更加灵活和健壮。

    当然非数字模式也可以在这里组合: (*[!-.0-9]* | *?-* | *.*.*).

    • 3
  3. Stéphane Chazelas
    2018-03-22T23:30:30+08:002018-03-22T23:30:30+08:00

    要将statements中的数字与正则表达式匹配case,您需要一个其通配符支持正则表达式的 shell。我只知道ksh93和那些。

    使用 ksh93 glob,您可以在 glob 模式中执行~(E)^[0-9]+$或~(E:^[0-9]+$)使用扩展正则表达式,或使用类似 perl 的正则表达式(也适用于基本正则表达式、增强正则表达式、SysV 正则表达式)。E~(P)^\d+$GXV

    所以:

    #! /bin/ksh93 -
    for i do
      case $i in
        (~(E)^[0-9]+$)
          n=$i;;
        (*)
          echo >&2 'Invalid argument!'
          usage
      esac
    done
    
    • 1

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve