A better way to compare text length percentage?

I have a solution, but it seems labored. I would like to compare strings return a value in percent out of 100.

Such as:

$ text1='a'; text2='abc'; s1=${#text1}; s2=${#text2}
$ [ "$s1" -gt "$s2" ] && di=$(( (($s1*100) / ($s2+1)) )) || [ "$s2" -gt "$s1" ] && di=$(( (($s2*100) / ($ls+1)) ))
$ echo $di
300

i.e., 'abc' is 300% longer than 'a'

For beginners: s1=${#text1} will return the length of $text1. In this case it would return '1' because it is one character long ('a').

I've looked at the man pages for 'diff' and some others and haven't figured out an easy way that this could be done in a more simple manner; yet, something tells me I'm missing something. I'm repeating the formulas, and I'm wondering if there is perhaps some way to do an inverse of a result... Anyways, it seems redundant.

Ideas?

Try:

echo ${#text1} ${#text2} |  awk '{print (100/$1*$2) }'

Hope this helps

Thank you. This is cool in that it seems to solve the 'division by zero' issue. :slight_smile:

Yet this works in only one way.

For example:

$ text1='ab'; text2='abcd'; s1=${#text1}; s2=${#text2}
$ echo ${#text1} ${#text2} |  awk '{print (100/$1*$2) }'
200

but

$ text1='abcd'; text2='ab'; s1=${#text1}; s2=${#text2}
$ echo ${#text1} ${#text2} |  awk '{print (100/$1*$2) }'
 50

I need both answers to say 200[%]. The text should be able to be swapped and still say the same value. The order does not matter to me, just how much bigger the bigger value is.

There must be some type of inverse equation or function/app that could be used. :confused:

Why?
In your 2nd example, the 2nd value is 50% of the first value. (${#text1} > ${#text2})
That is 100% accurate.

If you want to get only the bigger value, you need to switch the echo'd values, or you change the order within the awk statement.
Or you make a check for which command to take.

hth

EDIT:
Like:

bigger_value() { # NUM1 NUM2
# Returns the percentage of the bigger value
#
	[[ "$1" -le "$2" ]] && \
		echo $1 $2 |  awk '{print (100/$1*$2) "%"}' || \
		echo $2 $1 |  awk '{print (100/$1*$2) "%"}'
}
bigger_value $1 $2
2 Likes

Try also

awk -v"T1=$text1" -v"T2=$text2" 'BEGIN {PC = length(T1) / length (T2); print 100 * (PC<1?1/PC:PC) "%"}'
300%
4 Likes

a bit simpler - the order doesn't matter:

echo ${#text1} ${#text2} |  awk '{a=b=$1;($1>$2)?a=$2:b=$2;print (100/a*b) }'
2 Likes

Thank you all for you solutions. I ended up going with vegersh99's solution as it was the most brief. I liked RudiC's mathmatics with the inverse equation.

Since I cannot have 'division by zero' errors, I added the 'if' statement near the end. Found out that shell doesn't like to compare numbers with decimals so added the int() function as well:

echo ${#text1} ${#text2} | awk '{a=b=$1;($1>$2)?a=$2:b=$2;if(a*b){print int(100/a*b)}}'

Would really like to figure out how to get this to do the equation so as not to have the 'division by zero' error when one or two variables have an empty string. I've tried a bunch of things such as adding '1' to each variable and trying to make it up elsewhere, but each time the values are incorrect.

Anyways, for now, it's more concise, and it's being used in the code.

Thanks everyone!

Thats why I prefer functions:

bigger_value()  { # str1 str2
	[[ ! 2 -eq $# ]] && echo "Usage: $FUNCNAME str1 str2" >&2 && return 1
	echo ${#1} ${#2} | awk '{a=b=$1;($1>$2)?a=$2:b=$2;if(a*b){print int(100/a*b)}}' >&1
	return $?
}

hth

EDIT:
But you still need to figure out a way to 'remove the option' to pass an empty string.
And without knowing how/where you get those strings, we can not help.

1 Like

How about:

echo ${#text1} ${#text2} | awk '$1*$2{a=b=$1;($1>$2)?a=$2:b=$2;print int(100/a*b)}'
3 Likes

I prefer to only use functions when I'm going to use them more than once in my code. In this case, it's only used once.

The strings are regular text. So long as the examples as we've used them work, the program will work. As to the empty string, the code to not run if one or more strings are 0 in length works well enough for me.

1 Like

For those who care, I managed to come up with something more efficient. This code will also output even if there is no text:

a=${#text1};b=${#text2};echo $((a*b?(a>b?100*a/b:100*b/a):0))
2 Likes