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



Question:

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.


Solution:1

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 ':'   }  


Solution:2

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.


Solution:3

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  


Solution:4

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.


Solution:5

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]}  


Solution:6

$ 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.


Solution:7

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  


Solution:8

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.


Solution:9

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.


Solution:10

Using Bash.

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


Solution:11

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.


Solution:12

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


Solution:13

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.


Solution:14

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  


Solution:15

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


Solution:16

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  


Solution:17

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
Previous
Next Post »