我想比较两个字符串变量并打印两者相同的字符。我不确定如何执行此操作,我正在考虑使用comm
ordiff
但我不确定仅打印匹配字符的正确参数。他们还说他们接受文件,这些是字符串。任何人都可以帮忙吗?
输入:
a=$(echo "abghrsy")
b=$(echo "cgmnorstuvz")
输出:
"grs"
我想比较两个字符串变量并打印两者相同的字符。我不确定如何执行此操作,我正在考虑使用comm
ordiff
但我不确定仅打印匹配字符的正确参数。他们还说他们接受文件,这些是字符串。任何人都可以帮忙吗?
输入:
a=$(echo "abghrsy")
b=$(echo "cgmnorstuvz")
输出:
"grs"
你不需要做太多的工作来分配$a
和$b
shell变量,你可以......
a=abghrsy
b=cdgmrstuvz
现在,有一个经典的计算机科学问题,称为最长公共子序列1,与您的问题相似。
但是,如果您只想要常用字符,一种方法可以让 Ruby 完成工作......
$ ruby -e "puts ('$a'.chars.to_a & '$b'.chars.to_a).join"
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;
注意:我只是一个初学者。可能有更好的方法来做到这一点。
好问题+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 字段。休息是非常简单的使用comm
and tr
。
PS:如果您输入的字符串未排序,那么您需要管道 awk 的输出以对 awk 内的数组进行排序或排序。
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)}'
这假设分号不会出现在您的字符串中(如果不是这种情况,您可以使用任何其他字符)。
(感谢@CodeGnome 的回答)
echo "$b" | grep -o "[$a]" | tr -d '\n'
这不是一个广泛适用的解决方案,但它非常适合您的特定用例。这个想法是使用第一个变量作为字符类来匹配第二个字符串。例如:
a='abghrsy'
b='cgmnorstuvz'
echo "$b" | grep --only-matching "[$a]" | xargs | tr --delete ' '
这会grs
如您所料。请注意,使用xargs和tr只是为了从输出中删除换行符和空格;如果您愿意,您当然可以通过其他方式处理此问题。
不过,您真正要寻找的是一个固定的交叉点。虽然您可以在 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
这对我来说当然似乎更具可读性和健壮性,但是您的里程可能会有所不同。至少现在你有一些选项可供选择。