Bash shell测试一个字符串中的所有字符是否在另一个字符串中

时间:2015-04-12 20:02:51

标签: bash shell text-parsing

我有两个字符串,我想比较相等的字符,字符串必须包含确切的字符,但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'

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

2 个答案:

答案 0 :(得分:2)

您可以使用trmychars中的任何字符替换为符号,然后您可以测试结果字符串是否与符号p.e。,:

不同
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") ]] 
}

答案 1 :(得分:0)

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引用的字符串, $\n');如果您有 GNU sed,则可以简化为sed -r 's/(.)/\1\n/g
  • sort -u然后对生成的字符列表进行排序,并清除重复项(-u)。
  • comm -23比较两个字符串中不同的排序字符集,并打印 1st 字符串所特有的字符(comm使用3列布局,第1列包含第一个文件唯一的行,第二列包含第二列独有的行,以及两个输入文件共有的第三列打印行; -23抑制第二列和第三列,实际上只打印行这是第一个输入所特有的。)
  • [[ -z $charsUniqueToStr1 ]]然后测试$charsUniqueToStr1是否为空(-z);
    换句话说:如果第一个字符串不包含字符,则表示成功(退出代码0)。不包含在第二个字符串中;否则,失败(退出代码1);由于条件([[ .. ]])是函数中的 last 语句,其退出代码也成为函数的退出代码。