Tutorial :How to split a string in shell and get the last field


Suppose I have the string 1:2:3:4:5 and I want to get its last field (5 in this case). How do I do that using Bash? I tried cut, but I don't know how to specify the last field with -f.


You can use string operators:

$ foo=1:2:3:4:5  $ echo ${foo##*:}  5  

This trims everything from the front until a ':', greedily.

${foo  <-- from variable foo    ##   <-- greedy front trim    *    <-- matches anything    :    <-- until the last ':'   }  


Another way is to reverse before and after cut:

$ echo ab:cd:ef | rev | cut -d: -f1 | rev  ef  

This makes it very easy to get the last but one field, or any range of fields numbered from the end.


It's difficult to get the last field using cut, but here's (one set of) solutions in awk and perl

  $ echo 1:2:3:4:5 | awk -F: '{print $NF}'  5  $ echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'  5  


Assuming fairly simple usage (no escaping of the delimiter, for example), you can use grep:

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"  5  

Breakdown - find all the characters not the delimiter ([^:]) at the end of the line ($). -o only prints the matching part.


One way:

var1="1:2:3:4:5"  var2=${var1##*:}  

Another, using an array:

var1="1:2:3:4:5"  saveIFS=$IFS  IFS=":"  var2=($var1)  IFS=$saveIFS  var2=${var2[@]: -1}  

Yet another with an array:

var1="1:2:3:4:5"  saveIFS=$IFS  IFS=":"  var2=($var1)  IFS=$saveIFS  count=${#var2[@]}  var2=${var2[$count-1]}  

Using Bash (version >= 3.2) regular expressions:

var1="1:2:3:4:5"  [[ $var1 =~ :([^:]*)$ ]]  var2=${BASH_REMATCH[1]}  


$ echo "a b c d e" | tr ' ' '\n' | tail -1  e  

Simply translate the delimiter into a newline and choose the last entry with tail -1.


Using sed:

$ echo '1:2:3:4:5' | sed 's/.*://' # => 5    $ echo '' | sed 's/.*://' # => (empty)    $ echo ':' | sed 's/.*://' # => (empty)  $ echo ':b' | sed 's/.*://' # => b  $ echo '::c' | sed 's/.*://' # => c    $ echo 'a' | sed 's/.*://' # => a  $ echo 'a:' | sed 's/.*://' # => (empty)  $ echo 'a:b' | sed 's/.*://' # => b  $ echo 'a::c' | sed 's/.*://' # => c  


If your last field is a single character, you could do this:

a="1:2:3:4:5"    echo ${a: -1}  echo ${a:(-1)}  

Check string manipulation in bash.


There are many good answers here, but still I want to share this one using basename :

 basename $(echo "a:b:c:d:e" | tr ':' '/')  

However it will fail if there are already some '/' in your string. If slash / is your delimiter then you just have to (and should) use basename.

It's not the best answer but it just shows how you can be creative using bash commands.


Using Bash.

$ var1="1:2:3:4:0"  $ IFS=":"  $ set -- $var1  $ eval echo  \$${#}  0  


echo "a:b:c:d:e"|xargs -d : -n1|tail -1  

First use xargs split it using ":",-n1 means every line only have one part.Then,pring the last part.


for x in `echo $str | tr ";" "\n"`; do echo $x; done  


For those that comfortable with Python, https://github.com/Russell91/pythonpy is a nice choice to solve this problem.

$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'  

From the pythonpy help: -x treat each row of stdin as x.

With that tool, it is easy to write python code that gets applied to the input.


A solution using the read builtin:

IFS=':' read -a fields <<< "1:2:3:4:5"  echo "${fields[4]}"  

Or, to make it more generic:

echo "${fields[-1]}" # prints the last item  


Might be a little late with the answer though a simple solution is to reverse the ordering of the input string. This would allow you to always gain the last item no matter the length.

[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1  5  

It is important to note though, if using this method and the numbers are larger than 1 digit (Or larger than one character in any circumstance), you will need to run another 'rev' command over the piped output.

[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1  42  [chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev  24  

Hope I can help, cheers


If you like python and have an option to install a package, you can use this python utility.

# install pythonp  pythonp -m pip install pythonp    echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"  5  


Regex matching in sed is greedy (always goes to the last occurrence), which you can use to your advantage here:

$ foo=1:2:3:4:5  $ echo ${foo} | sed "s/.*://"  5  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »