Bash shell中测试,如果在一个字符串中的所有字符在另一个字符串(Bash shell tes

2019-10-22 14:41发布

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

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

Answer 1:

您可以使用tr以取代任何字符mychars用一个符号,那么你就可以测试,如果得到的字符串是从符号,PE有什么不同,:

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


Answer 2:

接受答案的解决方案是短暂的,聪明的,高效的

这里是一个低效率的选择如果你想知道哪些字符是唯一的1弦可能会感兴趣,返回一个排序,不同的列表:

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$//;} ; ${s/\n$//;}sed脚本。
    • 该命令是写在一个符合POSIX标准的方式,这复杂化了,由于具有在拼接\转义实际换行符(经由ANSI C-引用字符串, $\n' ); 如果已经GNU sed ,可以简化到sed -r 's/(.)/\1\n/g
  • sort -u然后排序结果字符的列表和杂草出重复( -u )。
  • comm -23比较不同组在两个串排序的字符,并打印那些特有的第一串( comm采用了3列布局,用含线特有的第一文件时,独有的含有第二列线的第一列第二列和第3列印刷线两个输入文件的共同点; -23抑制第二和第三列,仅有效地打印所特有的所述第一输入端的线)。
  • [[ -z $charsUniqueToStr1 ]]然后测试如果$charsUniqueToStr1为空( -z );
    换句话说:成功(退出代码0 )表示,如果第一串不包含字符。 这是不是也包含在第二根弦; 否则,失败(退出代码1 ); 由于条件(的[[ .. ]]是在函数的最后一条语句,其退出代码也成为了函数的退出代码。


文章来源: Bash shell test if all characters in one string are in another string