我想比较两个字符串变量并打印两者相同的字符。我不确定如何做到这一点,我想使用comm
或diff
,但我不确定正确的参数只打印匹配的字符。他们也说他们收录文件,这些都是字符串。有人可以帮忙吗?
输入:
a=$(echo "abghrsy")
b=$(echo "cgmnorstuvz")
输出:
"grs"
答案 0 :(得分:2)
您无需做太多工作来分配$a
和$b
shell变量,您可以......
a=abghrsy
b=cdgmrstuvz
现在,有一个名为longest common subsequence1的经典计算机科学问题与你的类似。
但是,如果你只想要常用字符,那么有一种方法可以让Ruby完成工作......
$ ruby -e "puts ('$a'.chars.to_a & '$b'.chars.to_a).join"
答案 1 :(得分: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;
注意:我只是一个初学者。可能有更好的方法来做到这一点。 子>
答案 2 :(得分: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 fiedls。休息非常直接使用comm
和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'
答案 3 :(得分:1)
这不是一个广泛适用的解决方案,但它非常适合您的特定用例。我们的想法是使用第一个变量作为字符类来匹配第二个字符串。例如:
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
这对我来说似乎更具可读性和稳健性,但您的里程可能会有所不同。至少现在你有一些选择可供选择。