Bash: How to remove the last character of a string?

In bash, how can one remove the last character of a string? In perl, the chop function would remove the last character. However, I do not know how to do the same job in bash.

Many thanks in advance.

There's a nice trimString() function in blib (the bash library link-> //bit.ly/i7tZWH) that does this. Of course it's still under development so your mileage may vary.

Essentially you can use something like... ${1:0:$((${#1}-1))}.

Note the subshell call may no be necessary...

Cheers,
Mikel King

No math needed:

foo="hello world"
echo ${foo%?}
hello worl
1 Like

You can pipe the line into awk like this...

script.sh | awk -F "until: " '{print $2}'

It's crude but works. I'm sure there are a dozen other ways but that's the first that comes to mind.

Cheers,
Mikel

carldamon

general use sed for only search and destroy missions. So I would not want to steer you in the wrong direction. But I believe you can through multiple pipings, or in combination with cut. I just find awk to be my go to tool for these sorts of manipulations.

Cheers,
m

Hello carldamon,

You seem to have barged into my thread by posting a question that is not related to my original post.

Remove your post from this thread, and create a new thread of your own, please.

LessNux (OP)

----------

Update:

Hello mikelking,

The question that carldamon posted in this thread has nothing to do with my original post. Therefore, your replies to carldamon have nothing to do with my original post. So, remove your replies to carldamon, please. However, keep your reply to my original post. Thanks.

LessNux (OP)

We can achieve that easily with traditional POSIX filters .

echo $x | sed s/.$//
1 Like

good shot bala .. :slight_smile:

Yes, this works, but it is horribly inefficient. Consider these two scripts which both chop the last character from the string stored in 'foo' and assign it to 'x':

#!/usr/bin/env bash
foo="hello world"
for (( i = 0; i < 1000; i++ ))
do
    x="${foo%?}"
done

and

#!/usr/bin/env bash
foo="hello world"
for (( i = 0; i < 1000; i++ ))
do
    x=$(echo $foo | sed s/.$// )
done

The first, using shell string manipulation, takes about 2/100ths of a second to execute:

time script1

real    0m0.02s
user    0m0.01s
sys     0m0.01s

while the second script takes more than 5 seconds:

time script2

real    0m5.03s
user    0m1.05s
sys     0m3.80s

If I've done my math correctly, that's about 2500 times slower, just to do this one assignment. Imagine if the script needed to chop 100 strings in its loop and did them all this way?

You'll note that the majority of the time in the second script is system time -- that's the time that bash had to wait on the system to start each sed process and deal with the I/O from sed back to bash.

In my opinion, agama's solution is the best of the bunch. It doesn't require any external tools and uses only a standard sh parameter expansion operation.

However, the use of echo in each solution makes is unsuitable for general purpose usage. If, $foo or ${foo%?} were to expand to something beginning with a leading dash, something resembling an option, the pipeline could give an unexpected result.

I suggest using printf %s "${foo%?}" in lieu of echo.

Regards,
Alister

1 Like

I've tried to delete but for whatever reason I am not able to. I didn't want to post this here but I can not even send a pm about this... kind of annoying...

m

Completely agree with you alister .
Thank you Agama for the enlightenment on the issue . :slight_smile: