Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find common characters between two strings in bash?

Tags:

string

bash

shell

For example:

s1="my_foo"
s2="not_my_bar"

the desired result would be my_o. How do I do this in bash?

like image 431
johannes Avatar asked Aug 04 '11 13:08

johannes


People also ask

How do you find common characters in two strings?

Approach: Count the frequencies of all the characters from both strings. Now, for every character if the frequency of this character in string s1 is freq1 and in string s2 is freq2 then total valid pairs with this character will be min(freq1, freq2). The sum of this value for all the characters is the required answer.

How do I compare two string variables in bash?

When comparing strings in Bash you can use the following operators: string1 = string2 and string1 == string2 - The equality operator returns true if the operands are equal. Use the = operator with the test [ command. Use the == operator with the [[ command for pattern matching.

What does %% mean in bash?

The operator "%" will try to remove the shortest text matching the pattern, while "%%" tries to do it with the longest text matching. Follow this answer to receive notifications.


3 Answers

My solution below uses fold to break the string into one character per line, sort to sort the lists, comm to compare the two strings and finally tr to delete the new line characters

comm -12 <(fold -w1 <<< $s1 | sort -u) <(fold -w1 <<< $s2 | sort -u) | tr -d '\n'

Alternatively, here is a pure Bash solution (which also maintains the order of the characters). It iterates over the first string and checks if each character is present in the second string.

s="temp_foo_bar"
t="temp_bar"
i=0
while [ $i -ne ${#s} ]
do
    c=${s:$i:1}
    if [[ $result != *$c* && $t == *$c* ]]
    then
      result=$result$c
    fi
    ((i++))
done
echo $result

prints: temp_bar

like image 121
dogbane Avatar answered Sep 23 '22 00:09

dogbane


Assuming the strings do not contain embedded newlines:

s1='my_foo' s2='my_bar'
intersect=$(
  comm -12 <(
    fold -w1 <<< "$s1" |
      sort -u
      ) <(
        fold -w1 <<< "$s2" |
          sort -u
          ) |
            tr -d \\n
            )

printf '%s\n' "$intersect" 

And another one:

tr -dc "$s2" <<< "$s1"
like image 27
Dimitre Radoulov Avatar answered Sep 26 '22 00:09

Dimitre Radoulov


a late entry, I've just found this page:

echo "$str2" |
  awk 'BEGIN{FS=""}
  { n=0; while(n<=NF) {
   if ($n == substr(test,n,1)) { if(!found[$n]) printf("%c",$n); found[$n]=1;} n++;
  } print ""}' test="$str1"

and another one, this one builds a regexp for matching (note: doesn't work with special characters, but that's not that hard to fix with anonther sed)

echo "$str1" |
  grep -E -o ^`echo -n "$str2" | sed 's/\(.\)/(|\1/g'; echo "$str2" | sed 's/./)/g'`
like image 28
Karoly Horvath Avatar answered Sep 25 '22 00:09

Karoly Horvath