How to extract last part of string in bash?

Some examples using parameter expansion

A="Some variable has value abc.123"
echo "${A##* }"

abc.123

Longest match on " " space

echo "${A% *}"

Some variable has value

Longest match on . dot

echo "${A%.*}"

Some variable has value abc

Shortest match on " " space

echo "${A%% *}"

some

Read more Shell-Parameter-Expansion


Yes; this:

A="Some variable has value abc.123"
echo "${A##* }"

will print this:

abc.123

(The ${parameter##word} notation is explained in §3.5.3 "Shell Parameter Expansion" of the Bash Reference Manual.)


Simplest is

echo "$A" | awk '{print $NF}'

Edit: explanation of how this works...

awk breaks the input into different fields, using whitespace as the separator by default. Hardcoding 5 in place of NF prints out the 5th field in the input:

echo "$A" | awk '{print $5}'

NF is a built-in awk variable that gives the total number of fields in the current record. The following returns the number 5 because there are 5 fields in the string "Some variable has value abc.123":

echo "$A" | awk '{print NF}'

Combining $ with NF outputs the last field in the string, no matter how many fields your string contains.


The documentation is a bit painful to read, so I've summarised it in a simpler way.

Note that the '*' needs to swap places with the ' ' depending on whether you use # or %. (The * is just a wildcard, so you may need to take off your "regex hat" while reading.)

  • ${A% *} - remove shortest trailing * (strip the last word)
  • ${A%% *} - remove longest trailing * (strip the last words)
  • ${A#* } - remove shortest leading * (strip the first word)
  • ${A##* } - remove longest leading * (strip the first words)

Of course a "word" here may contain any character that isn't a literal space.

You might commonly use this syntax to trim filenames:

  • ${A##*/} removes all containing folders, if any, from the start of the path, e.g.
    /usr/bin/git -> git
    /usr/bin/ -> (empty string)

  • ${A%/*} removes the last file/folder/trailing slash, if any, from the end:
    /usr/bin/git -> /usr/bin
    /usr/bin/ -> /usr/bin

  • ${A%.*} removes the last extension, if any (just be wary of things like my.path/noext):
    archive.tar.gz -> archive.tar

Tags:

String

Bash

Awk