【问题标题】:How to match an exact string in a string between quotes如何匹配引号之间的字符串中的确切字符串
【发布时间】:2019-07-01 13:57:32
【问题描述】:

我有一个变量,其中包含例如['Cars', 'House', 'Bike']。我希望能够搜索与字符串中包含的值完全匹配的值。


示例:

  • 我检查字符串Cars 是否存在于变量中。它应该返回true
  • 我检查字符串Car 是否存在于变量中。它应该返回false

我尝试了什么:

#!/bin/bash
search="Car"
arr="['Cars', 'House', 'Bike']"
if [[ $search =~ .*"$arr".* ]]; then
    echo "true"
else
    echo "false"
fi
# Output true | Expected false

另一个脚本:

#!/bin/bash
search="Cars"
arr="['Cars', 'House', 'Bike']"
check=0
grep -o "'[^']*'" <<<"$arr" | sed "s/'//g" |
while read -r elem; do
    if [ "$search" == "$elem" ]; then
         check=1
    fi
done
if [ "$check" == 1 ]; then
    echo "true"
else
    echo "false"
fi
# Output false | Expected true

【问题讨论】:

  • 解析bash中的JSON就像和婴儿锯木头一样:你真的不想这样做,如果你这样做,会有很多情绪上的痛苦。使用jq 或任何更高的编程语言。这些天来,Ruby、Python 和 Perl 都几乎可以保证安装,jq 很容易安装。见Parsing JSON with Unix toolsHow to check if element exists in array with jq
  • 我可以在我的脚本中使用 python。更新标签
  • 我认为这应该可以工作 variableTocheck='Cars listData = ['Cars', 'House', 'Bike'] valPresent = variableTocheck in listData 现在如果数据存在则 valPresent 将为真,否则它将为假
  • 显然,如果您能够只使用本机 bash 数组,而不是这个邪恶的 JSONoid,这个问题就会变成very different question。 :P
  • 我无法使用数组,因为我得到了 cURL 命令的响应

标签: python bash shell


【解决方案1】:

问题的第一个 Bash 示例代码中的正则表达式匹配存在几个问题。最大的问题是$search$arr 在匹配运算符的错误一侧。模式中缺少(带引号的)单引号也是一个严重的问题。无论如何,正则表达式匹配对于这个来说是多余的。更简单的“glob”模式匹配就足够了。试试这个:

#!/bin/bash

search=Car
arr="['Cars', 'House', 'Bike']"

if [[ $arr == *"'$search'"* ]]; then
    echo true
else
    echo false
fi

有关全局模式的信息,请参阅 glob - Greg's Wiki

【讨论】:

    【解决方案2】:

    正如其他人所说,使用 jq 在 bash 中解析 JSON。

    如果你真的不想这样,你可以尝试以下任何一种:

    search="'Car'" # add the single quotes to the search string
    # or
    search="\bCar\b" # \b is regex syntax for word boundary, meaning the word begins/ends there
    

    【讨论】:

      【解决方案3】:

      在 Python 中:

      search="Car"
      arr="['Cars', 'House', 'Bike']"
      
      import ast
      output = search in ast.literal_eval(arr)
      

      作为输出TrueFalse 的shell 脚本中的单行符:

      python -c 'import sys; import ast; print(sys.argv[1] in ast.literal_eval(sys.argv[2]))' "$search" "$arr"
      

      作为 shell 脚本中的单行符,返回 0(正常)或 -1(不正常)退出状态,这在 shell 中很常见:

      python -c 'import sys; import ast; sys.exit(0 if sys.argv[1] in ast.literal_eval(sys.argv[2]) else -1)' "$search" "$arr"
      

      【讨论】:

      • python需要包含在bash文件中
      【解决方案4】:

      一些关于如何用其他语言做到这一点的答案。我想你想知道为什么你的 bash 脚本不工作。

      根本原因是当您在 if 语句中设置 check=1 时,您处于不同的 shell 中,因此它不会影响外部脚本中定义的 check。这是一个不同的 shell,因为您将输入从另一个命令传递到 while。

      实现这项工作的几种方法:

      grep管道的输出发送到一个临时文件,然后在你的主shell脚本中执行while循环并从文件中读取输入。

      您还可以通过退出代码返回是否找到了要查找的字符串,并使用存储最后一个进程的退出代码的$? 变量将其保存在check 中。

      grep -o "'[^']*'" <<<"$arr" | sed "s/'//g" |
      while read -r elem; do
          if [ "$search" = "$elem" ]; then
               exit 1
          fi
      done 
      check=$?
      

      由于在您的 while 循环中使用退出代码基本上会使其成为 fgrep 的较差版本,因此您可以只使用 fgrep 并检查退出代码。

      【讨论】:

      • 您的 for...in 解决方案比我的任何建议都优雅!
      【解决方案5】:

      我找到了一种在循环中修改全局变量的方法。谢谢大家的建议。 这是脚本:

      #!/bin/bash
      
      search="Cars"
      arr="['Cars', 'House', 'Bike']"
      check=0
      for elem in $(grep -o "'[^']*'" <<<"$arr" | sed "s/'//g")
      do
          if [ "$search" == "$elem" ]; then
               check=1
          fi
      done
      if [ "$check" == 1 ]; then
          echo "true"
      else
          echo "false"
      fi
      # Output true | Expected true
      

      【讨论】:

        【解决方案6】:

        使用红宝石单线:

        $ json_arr="['Cars', 'House', 'Bike']"
        
        $ ruby -rjson -e '
            data = JSON.parse(ARGV.shift)
            puts data.include?(ARGV.shift)
        ' "${json_arr//\'/\"}" Cars
        true
        
        $ ruby -rjson -e '
            data = JSON.parse(ARGV.shift)
            puts data.include?(ARGV.shift)
        ' "${json_arr//\'/\"}" Donkey
        false
        

        注意,JSON 字符串必须使用双引号(https://json.org/),所以我使用 shell 的参数替换将单引号转换为双引号。

        【讨论】:

          【解决方案7】:

          如果你不想使用除了 bash 之外的任何东西,你可以使用 bash 数组。

          一如既往,有利有弊。 优点之一是您无需安装任何第三个程序即可使其工作,它也可以在其他 shell 中运行,例如 cygwin

          我写了一段代码例如:

          #!/bin/bash
          search="Car"
          arr="['Cars', 'House', 'Bike']"
          arr="$(printf "%s" "${arr}" | sed -e "s/,//g" -e "s/^\[/(/" -e "s/\]$/)/")"
          eval arr="${arr}"
          for var in ${arr[@]}; do
             if [ "${var}" = "${search}" ]; then
                printf "%s\n" "true"
                exit
             fi  
          done
          printf "%s\n" "false"
          

          无论如何,这段代码认为有些事情是理所当然的,但也有一些缺点。

          例如,您理所当然地认为您的所有输入都像样本一样,实际变量中没有任何“,”。

          【讨论】:

            猜你喜欢
            • 2019-10-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-16
            • 2020-11-13
            • 1970-01-01
            • 1970-01-01
            • 2014-05-02
            相关资源
            最近更新 更多