22

I have a space seperated string which is output by a command, which I like to pipe to cut, using -fd ' ' to split on spaces. I know I can use -f <n> to display field number <n>, but can I make it display the last field if I don't know the length of the string?

Or do I need to use a more flexible text editing tool like sed or awk?

αғsнιη
  • 35,092
  • 41
  • 129
  • 192
Arronical
  • 19,653
  • 18
  • 73
  • 128
  • I think cut command cannot support, but not sure, did you have a try with cut -d' ' -f- ? – αғsнιη Sep 30 '16 at 12:13
  • 3
    More ways of doing it: http://stackoverflow.com/questions/22727107/how-to-find-the-last-field-using-cut-linux – edwinksl Sep 30 '16 at 12:25
  • @KasiyA `-n` makes it the n from the start, `n-` is from n to the end, and there is the `--complement` option which reverses the selection. But no way to count the number of fields and act upon it as far as I can tell. – Arronical Sep 30 '16 at 12:25
  • 1
    This would make a nice extension to any cut program – qwr Jun 16 '21 at 16:49

4 Answers4

23

No cut can't do that. You could use two rev commands, like

echo 'foo bar baz' | rev | cut -d' ' -f1 | rev

but it's usually easier to use awk:

echo 'foo bar baz' | awk '{print $(NF)}'
Florian Diesch
  • 86,013
  • 17
  • 224
  • 214
10

You can do this using only shell, no external tool is needed, using Parameter Expansion:

${var##* }

var##* will discard everything from start up to last space from parameter (variable) var.

If the delimiter can be any whitespace e.g. space or tab, use character class [:blank:]:

${var##*[[:blank:]]}

Example:

$ var='foo bar spam egg'

$ echo "${var##* }"
egg


$ var=$'foo\tbar\tspam\tegg'

$ echo "$var"
foo    bar    spam    egg

$ echo "${var##*[[:blank:]]}"
egg
heemayl
  • 90,425
  • 20
  • 200
  • 267
  • I'd spoken about using parameter expansion in a comment on Severus Tux's answer, but the blank character class is useful information, thanks. – Arronical Oct 01 '16 at 21:19
4

I personally like Florian Diesch answer. But there is this way too.

a=$(echo "your string here" | wc -w)
echo "your string here" | cut -d' ' -f$a

Explanation:

wc -w gives the number of words. and cut cuts the last word

EDIT:

I figured another way of Doing it:

echo "Any random string here" | tac -s' ' | head -1
Severus Tux
  • 9,736
  • 9
  • 58
  • 97
2

Here is one using grep

$ echo "Change is Good" | grep -o '[^ ]*$'
Good

How it works:

  • grep with -o Print only the matched (non-empty) parts of a matching line.
  • The regexp [^ ]*$ matches anything from end until it found a space.

Another one liner from glenn jackman using perl

$ echo "Change is Good" | perl -lane 'print $F[-1]'
Good
sourav c.
  • 44,037
  • 20
  • 101
  • 128