Bash: как получить первое число в содержимом переменной

8

как получить первое число переменных

У меня есть переменная:

STR="My horse weighs 3000 kg but the car weighs more"
STR="Maruska found 000011 mushrooms but only 001 was not with meat"
STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

Мне нужно получить номера:

3000
11
20
Руи Ф Рибейро
источник

Ответы:

7

С помощью gawk установите разделитель записей RSна последовательность цифр. Текст, соответствующий RSшаблону, можно получить через RT. Добавьте 0к, RTчтобы заставить это число (таким образом, отбрасывая ведущие нули). Выход, как только напечатан первый экземпляр

awk -v RS=[0-9]+ '{print RT+0;exit}' <<< "$STR"

Или вот решение Bash

shopt -s extglob
read -r Z _ <<< "${STR//[^[:digit:] ]/}"
echo ${Z##+(0)}
Iruvar
источник
Ницца. Вы хотите уточнить?
Джейсонвриан
Я не понимаю Что я делаю не так (с версией awk)? gist.github.com/jamiejackson/d92750cc42442a527c6b94499a13bc79
Джейми Джексон,
@JamieJackson, убедитесь, что вы используете GNU awk aka gawk
iruvar
5

Вот один из способов сделать это:

echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'

Тестовое задание:

$ STR="My horse weighs 3000 kg but the car weighs more"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
3000

$ STR="Maruska found 000011 mushrooms but only 001 was not with meat"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
11

$ STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
20
cuonglm
источник
Какова цель sedв конце? Кажется, что прежде, чем мы перейдем к sed, у нас уже есть результат, которого мы хотим
Майкл
Нет, у вас есть № 2, 000011для которого вы должны удалить нули ведущих. Но вы можете упростить сопоставление, [1-9][0-9]*которое уберет лидирующие нули с самого начала: echo $STR | grep -o -E '[1-9][0-9]*'
CCH
2

Если ваша реализация grepне имеет -oили вы не используете Bash, вы можете сделать следующее:

printf "%.0f\n" $(printf "%s" "$string"|sed  's/^[^0-9]*//;s/[^0-9].*$//')
Джозеф Р.
источник
2
#!/bin/bash

string="My horse weighs 3000 kg but the car weighs more"

if [[ $string =~ ^([a-zA-Z\ ]*)([0-9]*)(.*)$ ]]
then
    echo ${BASH_REMATCH[1]}
fi  
Филипп
источник
1
Индекс должен быть 2 вместо 1. Но вам действительно не нужен этот комплекс регулярных выражений. В любом случае он потерпит неудачу, если в строке будут другие символы.
Приостановлено до дальнейшего уведомления.
2

Я поместил ваши строки в массив, чтобы его можно было легко повторить для этой демонстрации.

Это использует встроенное совпадение регулярных выражений Bash.

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

str[0]="My horse weighs 3000 kg but the car weighs more"
str[1]="Maruska found 000011 mushrooms but only 001 was not with meat"
str[2]="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

patt='([[:digit:]]+)'

for s in "${str[@]}"; do [[ $s =~ $patt ]] && echo "[${BASH_REMATCH[1]}] - $s"; done

Я включил квадратные скобки только для того, чтобы визуально выделить цифры.

Вывод:

[3000] - My horse weighs 3000 kg but the car weighs more
[000011] - Maruska found 000011 mushrooms but only 001 was not with meat
[0000020] - Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK

Чтобы получить числа без начальных нулей, самый простой способ состоит в том, чтобы вызвать преобразование в основание-10.

echo "$(( 10#${BASH_REMATCH[1]} ))"

Подставляя это, вывод выглядит так, как вы просили:

3000
11
20
Приостановлено до дальнейшего уведомления.
источник
1

Посмотрите регулярные выражения и man grep.

echo $STR | grep -o [0-9]*

и чтобы убрать начальные нули, относитесь к нему как к числу:

LIT=$(echo $STR | grep -o [0-9]*)
VAL=$(expr $LIT + 0)
echo $VAL
Sven
источник
Ваше решение терпит неудачу с переменными, содержащими два числа или число с нулем.
Cuonglm