【问题标题】:How to test if string matches a regex in POSIX shell? (not bash)如何测试字符串是否与 POSIX shell 中的正则表达式匹配? (不是 bash)
【发布时间】:2014-02-02 14:32:05
【问题描述】:

我使用的是 Ubuntu 系统 shell,不是 bash,我发现常规方式行不通:

#!/bin/sh
string='My string';

if [[ $string =~ .*My.* ]]
then
   echo "It's there!"
fi

错误[[:未找到!

我能做些什么来解决这个问题?

【问题讨论】:

  • 我知道 Bourne shell、Korn shell、bash、zsh 和其他一些,但我不知道什么是标准 shell...
  • 好吧,我的意思是系统shell /bin/sh 我已经更新了问题。
  • 好吧,POSIX sh 绝对符合“标准”的条件。 Ubuntu 中的 sh 是 Dash,它肯定会努力与 POSIX 兼容。

标签: regex shell sh posix


【解决方案1】:

[[ ... ]] 是一种 bash 主义。您可以通过使用grep 和普通的if 来使您的测试shell 不可知:

if echo "$string" | grep -q "My"; then
    echo "It's there!"
fi

【讨论】:

【解决方案2】:

为什么要对这种简单的模式使用 grep?通过 Sh 内置匹配引擎避免不必要的 fork

case "$value" in
  *XXX*)  echo OK ;;
  *) echo fail ;;
esac

它符合 POSIX。 Bash 对此有 simplified syntax

if [[ "$value" == *XXX* ]]; then :; fi

甚至是正则表达式:

[[ abcd =~ b.*d ]] && echo ok

【讨论】:

    【解决方案3】:

    你可以使用expr:

    if expr "$string" : "My" 1>/dev/null; then
      echo "It's there";
    fi
    

    这适用于shbash

    作为一个方便的功能:

    exprq() {
      local value
    
      test "$2" = ":" && value="$3" || value="$2"
      expr "$1" : "$value" 1>/dev/null
    }
    
    # Or `exprq "somebody" "body"` if you'd rather ditch the ':'
    if exprq "somebody" : "body"; then 
      echo "once told me"
    fi
    

    引用man expr:

       STRING : REGEXP
              anchored pattern match of REGEXP in STRING
    

    【讨论】:

    • 如果您确实需要常规的exoressiins,这是传统的便携式解决方案。但是,很多时候,case 就足够了; grep 也能完成这项工作,并且可能对大多数用户来说更熟悉。
    • expr 内置在 Bourne shell 中,而且速度更快,我们应该优先使用它而不是其他方法。
    • 如果您总是想在字符串的开头匹配,那就太好了,否则它将不起作用(他们为什么要设置这个限制?) - 顺便说一句,这个答案不满足 OP 的具体情况,匹配 字符串中的任何位置
    • @user9645 冷静点。 expr 采用正则表达式,这正是 OP 所要求的。您几乎可以搜索任何内容。
    【解决方案4】:
    [ "${string#*My}" != "$string" ] && echo "It's there!"
    
    ${...}
    

    ${...} 语法执行变量扩展;许多形式都是可移植的(包括有用的${foo#bar}${foo##bar}${foo%bar}${foo%%bar},但有些不是。

    ${!...} 进行间接变量扩展,这是一种bashism;请改用 eval。

    ${parameter/pattern/string} 执行模式替换,这是一种 bashism。有关解决此问题的建议,请参阅下一节。

    ${parameter:offset:length} 执行子字符串扩展,这是一种 bashism。有关解决此问题的建议,请参见下文。

    数组变量不可移植。在注意合适的分隔符的情况下,它们通常可以替换为一系列 ${foo#bar} 扩展等,而不会显着影响性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-02
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      相关资源
      最近更新 更多