【问题标题】:Bash shell test if all characters in one string are in another stringBash shell 测试一个字符串中的所有字符是否都在另一个字符串中
【发布时间】:2015-06-18 02:19:31
【问题描述】:

我有两个字符串要比较相等的字符,字符串必须包含确切的字符,但 mychars 可以有额外的字符。

mychars="abcdefg"
testone="abcdefgh"        # false h is not in mychars
testtwo="abcddabc"        # true all char in testtwo are in mychars

function test() {
    if each char in $1 is in $2  # PSEUDO CODE
    then
      return 1
    else
      return 0
    fi
}

if test $testone $mychars; then
   echo "All in the string" ;
else ;  echo "Not all in the string" ; fi

# should echo "Not all in the string" because the h is not in the string mychars

if test $testtwo $mychars; then
   echo "All in the string" ;
else ;  echo "Not all in the string" ; fi

# should echo 'All in the string'

最好的方法是什么?我的猜测是遍历第一个参数中的所有字符。

【问题讨论】:

    标签: bash shell text-parsing


    【解决方案1】:

    accepted answer's solution 简短、聪明、高效

    这是一个效率较低的替代方案如果您想知道哪些字符对于第一个字符串是唯一的,可能会很有趣,它以排序的、不同的列表形式返回:

    charTest() {
      local charsUniqueToStr1
      # Determine which chars. in $1 aren't in $2.
      # This returns a sorted, distinct list of chars., each on its own line.
      charsUniqueToStr1=$(comm -23 \
        <(sed 's/\(.\)/\1\'$'\n''/g' <<<"$1" | sort -u) \
        <(sed 's/\(.\)/\1\'$'\n''/g' <<<"$2" | sort -u))
      # The test succeeds if there are no chars. in $1 that aren't also in $2.
      [[ -z $charsUniqueToStr1 ]]
    }
    
    mychars="abcdefg" # define reference string
    
    charTest "abcdefgh" "$mychars" 
    echo $? # print exit code: 1 - 'h' is not in reference string
    
    charTest "abcddabc" "$mychars"
    echo $? # print exit code: 0 - all chars. are in reference string
    

    请注意,我已将 test() 重命名为 charTest() 以避免与 test 的名称冲突内置/实用程序

    • sed 's/\(.\)/\1\'$'\n''/g' 通过将每个字符放在单独的行上,将输入拆分为单个字符。
      • 请注意,该命令在末尾创建了一个额外的空行,但在这种情况下这无关紧要;要消除它,请将; ${s/\n$//;} 附加到sed 脚本中。
      • 该命令以符合 POSIX 的方式编写,由于必须在 \-转义 实际 换行符中拼接(通过 ANSI C 引用的字符串 @987654330 @);如果你有 GNU sed,你可以简化为 sed -r 's/(.)/\1\n/g
    • sort -u 然后对生成的字符列表进行排序并剔除重复项 (-u)。
    • comm -23 比较两个字符串中不同的已排序字符集并打印 1st 字符串唯一的字符(comm 使用 3 列布局,第一列包含第一个文件唯一的行,第 2 列包含第 2 列特有的行,第 3 列打印两个输入文件共有的行;-23 抑制第 2 列和第 3 列,有效地只打印第 1 输入特有的行)。
    • [[ -z $charsUniqueToStr1 ]] 然后测试 $charsUniqueToStr1 是否为空 (-z);
      换句话说:如果第一个字符串不包含字符,则表示成功(退出代码0)。也不包含在第二个字符串中;否则,失败(退出代码1);由于条件 ([[ .. ]]) 是函数中的 last 语句,其退出代码也成为 函数的退出代码。

    【讨论】:

      【解决方案2】:

      您可以使用trmychars 中的任何字符替换为符号,然后您可以测试生成的字符串是否与符号不同,例如:

      tr -s "[$mychars]" "." <<< "ggaaabbbcdefg"
      

      输出:

      .
      

      但是:

      tr -s "[$mychars]" "." <<< "xxxggaaabbbcdefgxxx"
      

      打印:

      xxx.xxx
      

      因此,您的函数可能如下所示:

      function test() {
          local dictionary="$1"
          local res=$(tr -s "[$dictionary]" "." <<< "$2")
          if [ "$res" == "." ]; then 
              return 1
          else
              return 0
          fi
      }
      

      更新:正如@mklement0 所建议的,整个函数可以通过以下方式缩短(并修复逻辑):

      function test() {
          local dictionary="$1"
          [[ '.' == $(tr -s "[$dictionary]" "." <<< "$2") ]] 
      }
      

      【讨论】:

      • 谢谢,我更新了答案以包含您的建议
      猜你喜欢
      • 2022-12-15
      • 2012-08-12
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 2017-02-21
      • 2015-05-13
      • 1970-01-01
      相关资源
      最近更新 更多