1

I need to compare two string in Bourne shell of the same fixed length. I need to compare each character against the place holder in the opposite string and find out how many differences there are. Does anyone have any suggestions on how to go about this?

I am just after a way of the number of differences i.e. if I compared aab & aac the differences would be 1.

This also has to be 100% bourne.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Thomas
  • 2,939
  • 6
  • 32
  • 29
  • You have to do this in Bourne and not Bash? What kind of antiquated system is this? – Mark Thomas Nov 16 '10 at 01:35
  • @Mark Thomas: What kind of programmer would use bashisms when a bourne solution does the trick? Who is *still* using bash when there's zsh? See, it's all a matter of preference and what you're used to or what your OS comes with. – Jens Aug 29 '11 at 10:47

6 Answers6

1

There are quite a few ways to accomplish what you seek (that I know of), but the following snippet of code should get you started:

STRING1="test"
STRING2="te5t"

COUNT=0
while [[ $COUNT -lt ${#STRING1}  ]]
do
    POS=$(($COUNT + 1))
    char1=$(echo "${STRING1}" | cut -c $POS)
    char2=$(echo "${STRING2}" | cut -c $POS)
    if [ $char1 != $char2 ]; then
        echo $char1
        echo $char2
    fi

    COUNT=$(($COUNT + 1))
done
1

If you don't mind creating temporary files, you can use the cmp method. With the Bourne shell you are pretty limited with what you can do. I would either use zsh/bash or if sh was essential, write a C program that did what I want.

If creating files every time is out of the question, you could create fifos, but this is really hackish and ugly, don't do it!

mkfifo cmp1
mkfifo cmp2
echo "abcd" > cmp1 &
echo "abce" > cmp2 &
DIFF_CHARS=`cmp -l cmp1 cmp2 | wc -l`

Process substitution in Bash or any modern shell makes this trivial and I would definitely try to use that.

rumbleca
  • 11
  • 2
1

This is pretty pure POSIX shell. It runs in Dash (as sh) and BusyBox Ash (as sh) and uses no external utilities (unless your shell doesn't have a builtin printf):

#!/bin/sh
string1="compare"
string2="c0mp4r3"

count=0
while [ -n "$string1" ]
do
    char1=$(printf "%1.1s" "$string1")
    char2=$(printf "%1.1s" "$string2")
    if [ "$char1" != "$char2" ]
    then
        count=$(($count + 1))
    fi
    string1=${string1#$char1}
    string2=${string2#$char2}
done
echo "There are $count differences"

This will run on the OBG1, the Heirloom Bourne Shell:

#!/usr/local/heirloom-bin/sh
string1="compare"
string2="c0mp4r3"

count=0
while [ -n "$string1" ]
do
    char1=`printf "%1.1s" "$string1"`
    char2=`printf "%1.1s" "$string2"`
    if [ "$char1" != "$char2" ]
    then
        count=`expr $count + 1`
    fi
    string1=`echo "$string1" | cut -c 2-`
    string2=`echo "$string2" | cut -c 2-`
done
echo "There are $count differences"

1 Oldie But Goody or Original Bourne Granddaddy

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
1
awk '{gsub(/[^[:alnum:]_[:blank:]]/, "", $0);for (i = 1; i <= NF; i++) {freq[$i]++}} END {for (word in freq){printf "%d\t%s\n", freq[word],word}}' {file} | sort -nr
Udo Held
  • 12,314
  • 11
  • 67
  • 93
äxl
  • 11
  • 1
0

This is probably answer you want ... Bash string difference

Using cmp to compare the two strings (diff won't give you the detail level you want.)

Community
  • 1
  • 1
ocodo
  • 29,401
  • 18
  • 105
  • 117
0

For educational purposes, here's a pure Bourne (and POSIX) solution, without extra forks. POSIX shells can run this even without any forks at all with COUNT=$((COUNT+1)):

#!/bin/sh

a=$1 b=$2

COUNT=0
while [ -n "$a" ]; do
  [ "${a%${a#?}}" != "${b%${b#?}}" ] && COUNT=`expr $COUNT + 1`
  a=${a#?} b=${b#?}
done
echo COUNT=$COUNT

Lets run this on the OP's strings:

$ ./x.sh aab aac
COUNT=1
Jens
  • 69,818
  • 15
  • 125
  • 179