Как разбить строку в оболочке и получить последнее поле - PullRequest
265 голосов
/ 02 июля 2010

Предположим, у меня есть строка 1:2:3:4:5, и я хочу получить ее последнее поле (5 в этом случае). Как мне это сделать с помощью Bash? Я пытался cut, но я не знаю, как указать последнее поле с -f.

Ответы [ 17 ]

375 голосов
/ 02 июля 2010

Вы можете использовать строковые операторы :

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

Это обрезает все от фронта до жадного ':'.

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }
329 голосов
/ 03 февраля 2012

Другой способ - повернуть назад до и после cut:

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

Это позволяет легко получить последнее, кроме одного поля, или любой диапазон полей, пронумерованных с конца.

67 голосов
/ 02 июля 2010

Трудно получить последнее поле, используя cut, но вот (один набор) решений в awk и 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
26 голосов
/ 02 июля 2010

Предполагая довольно простое использование (например, без экранирования, вы можете использовать grep:

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

Разбивка - найти все символы, не разделитель ([^:]) в конце строки ($). -o печатает только соответствующую часть.

18 голосов
/ 02 июля 2010

В одну сторону:

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

Другой, используя массив:

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

Еще один с массивом:

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

Использование Bash (версия>= 3.2) регулярные выражения:

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
9 голосов
/ 24 декабря 2013
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

Просто переведите разделитель в новую строку и выберите последнюю запись с помощью tail -1.

6 голосов
/ 10 ноября 2016

Использование 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
4 голосов
/ 26 апреля 2016

Здесь есть много хороших ответов, но все же я хочу поделиться этим, используя basename :

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

Однако завершится неудачей, если уже есть некоторые '/'в вашей строке .Если косая черта / является вашим разделителем, то вам просто нужно (и нужно) использовать базовое имя.

Это не самый лучший ответ, но он просто показывает, как вы можете быть креативными, используя команды bash.

4 голосов
/ 13 ноября 2013

Если ваше последнее поле состоит из одного символа, вы можете сделать это:

a="1:2:3:4:5"

echo ${a: -1}
echo ${a:(-1)}

Проверить манипулирование строками в bash .

2 голосов
/ 07 декабря 2016
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

Сначала используйте xargs, разделите его, используя «:», - n1 означает, что каждая строка имеет только одну часть. Затем выводит последнюю часть.

...