【问题标题】:Check for substring in Shell without Bashisms在没有 Bashisms 的情况下检查 Shell 中的子字符串
【发布时间】:2014-08-28 05:52:46
【问题描述】:

我正在尝试编写一个 shell 脚本,我必须在其中查找字符串中是否存在 -32。不幸的是,我必须在不使用任何 bashism 的情况下这样做,因为它必须在运行 Dash 的计算机上运行。

我尝试了case ${1+"$@"} in *-32*);;,但这会得到类似 -321 的结果。有没有办法使用正则表达式或其他东西来寻找那个标志?它周围可以有其他标志,由字符串中的空格分隔。

我认为我需要的正则表达式查找 -32,后面有空格或行尾。 -32(\s|$)

我对正则表达式很陌生,所以我不确定这是否是最好的方法。任何帮助将不胜感激!

谢谢!

【问题讨论】:

  • 为什么不循环遍历参数而不是将它们视为一个字符串?
  • 抱歉,这是一个愚蠢的问题,但我该怎么做呢?
  • for arg; do if [ "X$arg" = "X-32" ] ...; done
  • 成功了,谢谢!

标签: regex linux shell dash-shell


【解决方案1】:

您可以使用grep 与字边界:

grep -E '-32\b' FILE

\b 匹配“单词边界”= 字母数字字符和非字母数字字符之间的位置。

在默认语言环境中,“字母数字字符”(如上面使用的术语)表示与字符类[a-zA-Z0-9_] 匹配的任何字符(即任何数字、任何字母A-Z 和下划线)。

以类似的方式,\B 匹配任何没有单词边界的位置(即任何位置,其两侧的字符属于相同类型,要么是字母数字字符,要么都是非字母数字)。

因此,如果您想确保减号之前必须加上一个非字母数字字符(例如空格),您可以编写以下代码:

grep -E '\B-32\b' FILE

这将匹配xx -32 xx(减号前有一个空格)但xx-32 xx(没有空格)。由于空格和减号都是非字母数字,\B 将在它们之间匹配,但 \b 不会。

如果您想确保减号前面是字母数字字符,您可以编写以下内容:

grep -E '\b-32\b' FILE

匹配例如x-32 x(无空格),但不是x -32 x(减号前有空格)。

【讨论】:

    【解决方案2】:

    所有这些示例都使用内置函数,并且完全兼容dash

    查找子字符串

    如果您实际上是在寻找字符串的子字符串,您可以使用caseif

    让我通过使用每个函数编写两个不同的match 函数来进行说明。如果你很懒,你可以将这些函数中的任何一个剪切/粘贴到你的脚本中并使用:

    if match -32 "$STRING"; then
        echo "found '-32'!"
    fi
    

    例如如果您想在开头和结尾搜索$SUBSTR,并用空格与字符串的其余部分分隔,您可以使用以下内容:

    function match() {
        local SUBSTR="$1" STR="$2"                # get args
        case " $STR " in                          #   add extra spaces
            *" $SUBSTR "*) return 0 ;;            #   return true if match
        esac
        return 1                                  # no match: return false
    }
    

    (在上面的函数中,我在$STR 周围添加了空格,因此我不必在字符串的开头和结尾显式查找匹配项。)

    function match() {
        local SUBSTR=" $1 " STR=" $2 "            # get args + add extra spaces
        [ "${STR#*"$SUBSTR"}" != "$STR" ] \
            && return 0                           # match: return true
        return 1                                  # no match: return false
    }
    

    这个if 声明有点棘手。表达式${STR#*"$SUBSTR"} 部分意思是,取$STR,并从它的开头删除所有内容,直到第一次出现$SUBSTR(如果找不到$SUBSTR,不要删除任何内容)。然后我们将其与原始的$STR 进行比较,如果它们不同相同,我们就知道找到了子字符串。

    寻找论据

    现在,如果您实际上是在寻找一个参数,您可以使用上述任何一个函数,然后简单地使用match "-32" "$*",但会找到所有子字符串,并且不会将参数彼此区分开(例如在不太可能发生任何参数,例如文件名,碰巧包含匹配的字符串'-32'。

    在这种情况下,最好只查看参数。我再给你写一个小函数,你可以用argmatch "$ARG" "$@"调用

    argmatch() {
        local FIND="$1" ARG; shift               # get $FIND arg, remove it from $@
        for ARG; do                              # loop $@
            [ "$ARG" = "$FIND" ] && return 0     #   found? then return true
        done
        return 1                                 # return false
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多