Link to home
Start Free TrialLog in
Avatar of YZlat
YZlatFlag for United States of America

asked on

Getting the last character of a string with ksh

I need to capture the last character in a string, and if it equals to 's', I need to take one action, if not, then another.

I have

str="tests"
echo ${str:(-1)}

 ch= ${str:(-1)}

if [ ch == 's' ]
then


else


fi

I get an error

${str:(-1)}: 0403-011 The specified substitution is not valid for this command.
ASKER CERTIFIED SOLUTION
Avatar of woolmilkporc
woolmilkporc
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Try this:

$ str='hello'
$ echo ${str:${#str}-1}

Open in new window

Sorry, "expr" is not a shell builtin. My mistake!

And this is shorter:

str="tests"
ch=$(expr substr $str ${#str}  1)
echo  $ch
Avatar of YZlat

ASKER

What is #str?
1) ${str#<pattern>} strips <pattern> off of the front of the variable's content.

2) ${str%<pattern>} strips <pattern> off the end of the variable's content.

3) ${str%?} strips off the last character of the content, so we can use format (2) to strip off the result of (3).
Does

  ${str: -1}

work?  Note the space between the : and the -
${#str} contains the lenght of $str
Avatar of YZlat

ASKER

both

echo ${str:${#str}-1}

and

${str: -1}


gave me the same error
And this?

echo ${str#${str%?}}

?
Avatar of Tintin
Tintin

The string functions available in ksh vary depending on what version you have.

This will work for all versions of ksh (and bash)

str='abcdefg'
echo $str | cut -c${#str}

Open in new window

The ${str: -1} construction is not in ksh88, but is in ksh93.  Does AIX still use ksh88?
@simon3270:

AIX ships ksh88 as /usr/bin/ksh. ksh93 is also shipped, but as /usr/bin/ksh93.

/bin/ksh and /bin/sh are both hardlinked to /usr/bin/ksh which makes ksh88 kind of a default.

wmp
Thanks @wmp.

So, ${str: -1} (and various other solutions) could be used if the first line of the script was changed to

    #!/usr/bin/ksh93

That said, Tintin's solution is the most portable, though you could also do

    ch=`echo $str | sed 's/^.*\(.\)$/\1/'`
This works in ksh88, ksh93 and bash:

echo ${str#${str%?}}
unless you have something like
str='***'
Yep.

echo "${str#${str%?}}"

but then also

ch=`echo "$str" | sed 's/^.*\(.\)$/\1/'`
echo "$ch"

( simon3270's solution).
quotes fix echo `"$str" | sed 's/^.*\(.\)$/\1/'`
but not "${str#${str%?}}"
(at least not in all versions of ksh88, ksh93 and bash)
Interesting.

ksh93 and bash require this:

echo "${str#"${str%?}"}"
if it is the nested ${} that is causing the problem, you could (going back to the original request) have:
if [ "${str%?}s" = "$str" ]; then
  : string ends with s - do the required work
fi

Open in new window

Avatar of YZlat

ASKER

Thanks!