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

В баш,

Как я могу найти последнее вхождение группы цифр в строке? Итак, если у меня есть

string="123 abc 456"

Я бы получил

456

И если бы я имел

string="123 123 456"

Я бы еще получил

456
0
Xi Ling 20 Авг 2018 в 18:26

7 ответов

Лучший ответ
 grep -o '[0-9]\+' file|tail -1
  • grep -o перечисляет только совпадающий текст
  • tail -1 выводит только последнее совпадение

Хорошо, если у вас есть строка:

grep -o '[0-9]\+' <<< '123 foo 456 bar' |tail -1
1
Kent 20 Авг 2018 в 15:41

Без внешних утилит (таких как sed, awk, ...):

$ s="123 abc 456"
$ [[ $s =~ ([0-9]+)[^0-9]*$ ]] && echo "${BASH_REMATCH[1]}"
456

BASH_REMATCH - это специальный массив, которому назначены совпадения из [[ ... =~ ... ]].


Тестовый код:

str=("123 abc 456" "123 123 456" "123 456 abc def" "123 abc" "abc 123" "123abc456def")

for s in "${str[@]}"; do
    [[ $s =~ ([0-9]+)[^0-9]*$ ]] && echo "$s -> ${BASH_REMATCH[1]}"
done

Вывод:

123 abc 456 -> 456
123 123 456 -> 456
123 456 abc def -> 456
123 abc -> 123
abc 123 -> 123
123abc456def -> 456
2
PesaThe 20 Авг 2018 в 17:31

Вы можете использовать это sed для извлечения последнего числа в строке:

sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/'

Примеры:

sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 abc 456'
456

sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 456 foo bar'
456

sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 123 456'
456

sed -E 's/(.*[^0-9]|^)([0-9]+).*/\2/' <<< '123 x'
123

Сведения о регулярном выражении:

  • (.*[^0-9]|^): совпадение 0 или более символов в начале с последующим началом нецифровой строки ИЛИ.
  • ([0-9]+): совпадение цифр 1+ и захват в группе № 2
  • .*: сопоставить оставшиеся символы до конца строки
  • \2: замените его обратной ссылкой № 2 (то, что мы записали в группе № 2)
1
anubhava 20 Авг 2018 в 17:33

Вы можете использовать регулярные выражения в Bash:

$ echo "$string"
123 abc 456
$ [[ $line =~ (^.*[ ]+|^)([[:digit:]]+) ]] && echo "${BASH_REMATCH[2]}"
456

Если вы хотите захватывать неограниченное количество строк, таких как 456 или abc123def456, вы можете сделать:

$ echo "$string"
test456text
$ [[ $string =~ ([[:digit:]]+)[^[:digit:]]*$ ]] && echo "${BASH_REMATCH[1]}"
456

Но если вы собираетесь использовать внешний инструмент, используйте awk.

Вот демонстрация Bash vs Awk, чтобы получить последнее поле цифр в строке. Они предназначены для цифр с разделителями ' ' или в конце или в начале строки.

Данный:

$ cat file
456
123 abc 456
123 123 456
abc 456
456 abc
123 456 foo bar
abc123def456

Вот тестовый сценарий:

while IFS= read -r line || [[ -n $line ]]; do
    bv=""
    av=""
    [[ $line =~ (^.*[ ]+|^)([[:digit:]]+) ]] && bv="${BASH_REMATCH[2]}"
    av=$(awk  '{for (i=1;i<=NF;i++) if (match($i, /^[[:digit:]]+$/)) last=$i; print last}' <<< "$line")
    printf "line=%22s bash=\"%s\" awk=\"%s\"\n" "\"$line\"" "$bv" "$av"
done <file

Печать:

line=                 "456" bash="456" awk="456"
line=         "123 abc 456" bash="456" awk="456"
line=         "123 123 456" bash="456" awk="456"
line=             "abc 456" bash="456" awk="456"
line=             "456 abc" bash="456" awk="456"
line=     "123 456 foo bar" bash="456" awk="456"
line=        "abc123def456" bash="" awk=""
1
dawg 21 Авг 2018 в 00:11

Простой ответ с gawk:

echo "$string" | gawk -v RS=" " '/^[[:digit:]]+$/ { N = $0 } ; END { print N }'

С RS=" " мы читаем каждое поле как отдельную запись. Затем мы сохраняем последний найденный номер и печатаем его.

$ string="123 abc 456 abc"
$ echo "$string" | gawk -v RS=" " '/^[[:digit:]]+$/ { N = $0 } ; END { print N }'
456
0
user1461760user1461760 20 Авг 2018 в 18:00

Еще один способ сделать это с чистым Bash:

shopt -s extglob            # enable extended globbing - for *(...)

tmp=${string%%*([^0-9])}    # remove non-digits at the end
last_digits=${tmp##*[^0-9]} # remove everything up to the last non-digit

printf '%s\n' "$last_digits"
1
pjh 20 Авг 2018 в 18:41

Это хорошая работа для расширения параметров:

$ string="123 abc 456"
$ echo ${string##* }
456
0
chthonicdaemon 20 Авг 2018 в 15:40
51934004