【问题标题】:How to find substring inside a string (or how to grep a variable)? [duplicate]如何在字符串中查找子字符串(或如何 grep 变量)? [复制]
【发布时间】:2023-03-29 06:36:02
【问题描述】:

我正在使用 BASH,但我不知道如何找到子字符串。它一直失败,我有一个字符串(这应该是一个数组吗?)

下面,LIST 是数据库名称的字符串列表,SOURCE 是回复,其中一个数据库。以下仍然不起作用:

echo "******************************************************************"
echo "*                  DB2 Offline Backup Script                     *"
echo "******************************************************************"
echo "What's the name of of the  database you would like to backup?"
echo "It will be named one in this list:"
echo ""
LIST=`db2 list database directory | grep "Database alias" | awk '{print $4}'`
echo $LIST
echo ""
echo "******************************************************************"
echo -n ">>> "
read -e SOURCE

if expr match "$LIST" "$SOURCE"; then
    echo "match"
    exit -1
else
    echo "no match"
fi
exit -1

我也试过了,但是不行:

if [ `expr match "$LIST" '$SOURCE'` ]; then

【问题讨论】:

标签: linux string bash db2


【解决方案1】:
LIST="some string with a substring you want to match"
SOURCE="substring"
if echo "$LIST" | grep -q "$SOURCE"; then
  echo "matched";
else
  echo "no match";
fi

【讨论】:

  • 使用这种方法需要考虑的 2 个问题: (1) grep 使用正则表达式,因此某些字符会匹配意外或导致错误; (2) 使用 grep (或任何未内置于 bash 的东西)会产生一个运行速度较慢的单独进程(仅在较大规模的情况下才重要)。
【解决方案2】:

你也可以用通配符比较:

if [[ "$LIST" == *"$SOURCE"* ]]

【讨论】:

  • 您应该始终引用字符串,例如:if [[ "$list" == *"$source"* ]]
  • 请注意if [[ *"$SOURCE"* == "$LIST$" ]] 是假的。
  • 我已经确认订单很重要/强制 - 所以*"$SOURCE"* 必须是正确的 - 否则总是返回 false - 为什么会有这种行为?
【解决方案3】:

这在 Bash 中有效,无需派生外部命令:

function has_substring() {
   [[ "$1" != "${2/$1/}" ]]
}

示例用法:

name="hello/world"
if has_substring "$name" "/"
then
   echo "Indeed, $name contains a slash!"
fi

【讨论】:

  • 此解决方案的优势在于它不依赖任何外部命令或文件描述符(通过重定向或管道)。
  • 请注意,这是使用正则表达式来搜索子字符串(并且还会进行异地替换),因此搜索中的特殊字符(子字符串)可能会导致意外结果。但是如果正则表达式很好,那么为什么不直接进行正则表达式搜索(即不需要替换)?语法示例:if [[ "$string" =~ $substring ]]
【解决方案4】:

如果你使用 bash,你可以说

if grep -q "$SOURCE" <<< "$LIST" ; then
    ...
fi

【讨论】:

    【解决方案5】:

    如果只想查找单个字符,可以使用“索引”,例如:

    LIST="server1 server2 server3 server4 server5"
    SOURCE="3"
    if expr index "$LIST" "$SOURCE"; then
        echo "match"
        exit -1
    else
        echo "no match"
    fi
    

    输出是:

    23
    match
    

    【讨论】:

      【解决方案6】:
      expr match "$LIST" '$SOURCE'
      

      这个函数不起作用,因为这个函数从字符串的开头搜索 $SOURCE,如果找到 else 0,则返回模式 $SOURCE 之后的位置。所以你必须编写另一个代码:

      expr match "$LIST" '.*'"$SOURCE" or expr "$LIST" : '.*'"$SOURCE"
      

      表达式 $SOURCE 必须用双引号引起来,以便解析器可以设置替换。单引号不能替代,上面的代码将从 $LIST 的开头搜索文本字符串 $SOURCE。如果您需要字符串的开头减去长度 $SOURCE,例如 ${#SOURCE}。 你也可以写

      expr "$LIST" : ".*\($SOURCE\)"
      

      这个函数只是从 $LIST 中提取 $SOURCE 并返回它。你会得到空字符串。但是他们对双双引号有问题。我不知道如果不使用其他变量它是如何解决的。 这是一个轻量级的解决方案。所以你可以用C写。有现成的函数strstr。 不要使用 expr 索引,所以很有吸引力。但索引搜索不是子字符串,只有第一个字符。

      【讨论】:

        【解决方案7】:

        expr 使用 而不是 [ 而不是在它里面,并且变量只在双引号内展开,所以试试这个:

        if expr match "$LIST" "$SOURCE"; then
        

        但我不太清楚 SOURCE 应该代表什么。

        看起来您的代码将从标准输入中读取模式,如果它与数据库别名匹配则退出,否则它会回显“ok”。这就是你想要的吗?

        【讨论】:

          【解决方案8】:

          好吧,这样的事情怎么样:

          PS3="Select database or <Q> to quit: "
          select DB in db1 db2 db3; do
             [ "${REPLY^*}" = 'Q' ] && break
             echo "Should backup $DB..."
          done
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-08-27
            • 2011-01-07
            • 2011-04-13
            • 1970-01-01
            • 2019-10-01
            • 1970-01-01
            • 2021-04-21
            • 2020-06-11
            相关资源
            最近更新 更多