2

我想比较两个字符串变量并打印两者相同的字符。我不确定如何执行此操作,我正在考虑使用commordiff但我不确定仅打印匹配字符的正确参数。他们还说他们接受文件,这些是字符串。任何人都可以帮忙吗?

输入:

a=$(echo "abghrsy")
b=$(echo "cgmnorstuvz")

输出:

"grs"
4

4 回答 4

2

你不需要做太多的工作来分配$a$bshell变量,你可以......

a=abghrsy
b=cdgmrstuvz

现在,有一个经典的计算机科学问题,称为最长公共子序列1,与您的问题相似。

但是,如果您只想要常用字符,一种方法可以让 Ruby 完成工作......

$ ruby -e "puts ('$a'.chars.to_a & '$b'.chars.to_a).join"

1.不要与不同的最长公共子串问题混淆。

于 2013-04-06T04:32:35.167 回答
1

使用 gnu coreutils(受@DigitalRoss 启发)..

a="abghrsy"
b="cgmnorstuvz"

echo "$(comm -12 <(echo "$a" | fold -w1 | sort | uniq) <(echo "$b" | fold -w1 | sort | uniq) | tr -d '\n')"

将打印grs。我假设你只想要 uniq 字符。

更新: 修改为破折号..

 #!/bin/dash

 string1=$(printf "$1" | fold -w1 | sort | uniq | tr -d '\n');
 string2=$(printf "$2" | fold -w1 | sort | uniq | tr -d '\n');

 while [ "$string1" != "" ]; do
   c1=$(printf '%s\n' "$string1" | cut -c 1-1 )
   string2=$(printf "$2" | fold -w1 | sort | uniq | tr -d '\n');
   while [ "$string2" != "" ]; do
     c2=$(printf '%s\n' "$string2" | cut -c 1-1 )
     if [ "$c1" = "$c2" ]; then
       echo "$c1\c"
     fi
     string2=$(printf '%s\n' "$string2" | cut -c 2- )
   done
   string1=$(printf '%s\n' "$string1" | cut -c 2- )
 done
 echo;

注意:我只是一个初学者。可能有更好的方法来做到这一点。

于 2013-04-06T04:47:33.583 回答
1

好问题+1。

您可以使用 awk 技巧来完成这项工作。

a=abghrsy
b=cdgmrstuvz
comm -12 <(echo $a|awk -F"\0" '{for (i=1; i<=NF; i++) print $i}') <(echo $b|awk -F"\0" '{for (i=1; i<=NF; i++) print $i}')|tr -d '\n'

输出:

grs

注意使用awk -F"\0"它将输入字符串逐个字符地分解为不同的 awk 字段。休息是非常简单的使用command tr

PS:如果您输入的字符串未排序,那么您需要管道 awk 的输出以对 awk 内的数组进行排序或排序。

更新:仅 awk 解决方案(无 comm):

echo "$a;$b" | awk -F"\0" '{scnd=0; for (i=1; i<=NF; i++) {if ($i!=";") {if (!scnd) arr1[$i]=$i; else if ($i in arr1) arr2[$i]=$i} else scnd=1}} END { for (a in arr2) printf("%s", a)}'

这假设分号不会出现在您的字符串中(如果不是这种情况,您可以使用任何其他字符)。

更新2:我认为最简单的解决方案是使用 grep -o

(感谢@CodeGnome 的回答)

echo "$b" | grep -o "[$a]" | tr -d '\n'
于 2013-04-06T05:36:06.727 回答
1

通过 GNU Grep 使用字符类

这不是一个广泛适用的解决方案,但它非常适合您的特定用例。这个想法是使用第一个变量作为字符类来匹配第二个字符串。例如:

a='abghrsy'
b='cgmnorstuvz'
echo "$b" | grep --only-matching "[$a]" | xargs | tr --delete ' '

这会grs如您所料。请注意,使用xargstr只是为了从输出中删除换行符和空格;如果您愿意,您当然可以通过其他方式处理此问题。

设置交点

不过,您真正要寻找的是一个固定的交叉点。虽然您可以在 shell 中“使用它”,但最好使用 Ruby、Python 或 Perl 之类的语言来执行此操作。

红宝石单线

如果您需要与现有的 shell 脚本集成,可以在当前脚本中像这样调用一个使用 Bash 变量的简单 Ruby 单行器:

a='abghrsy'
b='cgmnorstuvz'
ruby -e "puts ('$a'.split(//) & '$b'.split(//)).join"

一个红宝石脚本

你当然可以通过在 Ruby 中完成整个事情来让事情变得更优雅。

string1_chars = 'abghrsy'.split //
string2_chars = 'cgmnorstuvz'.split //
intersection  = string1_chars & string2_chars
puts intersection.join

这对我来说当然似乎更具可读性和健壮性,但是您的里程可能会有所不同。至少现在你有一些选项可供选择。

于 2013-04-06T06:13:32.900 回答