Как сохранить / удалить числа в переменной в оболочке? - PullRequest
0 голосов
/ 16 июня 2019

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

disk=/dev/sda1

Я хочу извлечь:

  • только нечисловая часть (т.е. / dev / sda)
  • только числовая часть (т.е. 1)

Я собираюсь использовать его в сценарии, где мне нужен диск и номер раздела. Как я могу сделать это в оболочке (в основном bash и zsh)?

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

В основном я пробовал:

echo ${disk##[:alpha:]}

и

echo ${disk##[:digit:]}

Но никто не работал. Оба вернулись /dev/sda1

Ответы [ 3 ]

3 голосов
/ 16 июня 2019

С bash и zsh и расширением параметра:

disk="/dev/sda12"
echo "${disk//[0-9]/} ${disk//[^0-9]/}"

Выход:

/dev/sda 12
1 голос
/ 17 июня 2019

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

Идея состоит в том, чтобы удалить последнее число, поэтому вы хотите использовать Удалить соответствующий шаблон суффикса (${parameter%%word}).Здесь мы удаляем самый длинный экземпляр сопоставленного шаблона, описанного word.Представление однозначных чисел легко сделать с помощью шаблона [0-9], однако многозначные числа сложнее.Для этого вам нужно использовать расширенные выражения glob:

*(pattern-list): Соответствует нулю или более вхождений данных шаблонов

Так что если выЧтобы удалить последний номер, вы используете:

$ shopt -s extglob
$ disk="/dev/sda1"
$ echo "${disk#${disk%%*([0-9])}} "${disk%%*([0-9])}"
1 dev/sda
$ disk="/dev/dsk/c0t2d0s0"
$ echo "${disk#${disk%%*([0-9])}} "${disk%%*([0-9])}"
0 /dev/dsk/c0t2d0s

Мы должны использовать ${disk#${disk%%*([0-9])}}, чтобы удалить префикс.По сути, он ищет последний номер, удаляет его, использует остаток и снова удаляет эту часть.

Вы также можете использовать замену шаблона (${parameter/pattern/string}) с якорями %и # для привязки шаблона к началу или концу параметра.(см. man bash для получения дополнительной информации).Это полностью эквивалентно предыдущему решению:

$ shopt -s extglob
$ disk="/dev/sda1"
$ echo "${disk/${disk/%*([0-9])}/}" "${disk/%*([0-9])}"
1 dev/sda
$ disk="/dev/dsk/c0t2d0s0"
$ echo "${disk/${disk/%*([0-9])}/}" "${disk/%*([0-9])}"
0 /dev/dsk/c0t2d0s
1 голос
/ 16 июня 2019

Расширения вроде работают наоборот. С [:digit:] вы будете соответствовать только одной цифре. Вам нужно сопоставить все до или из цифры, поэтому вам нужно использовать *.

Следующее выглядит нормально:

$ echo ${disk%%[0-9]*} ${disk##*[^0-9]}
/dev/sda 1

Чтобы использовать [:digit:], вам нужны двойные скобки, потому что класс персонажа - [:class:], а сам он должен быть внутри [ ]. Вот почему я предпочитаю 0-9, меньше печатать *. То же самое, что и выше:

echo ${disk%%[[:digit:]]*} ${disk##*[^[:digit:]]}

* - Теоретически они могут быть не равны, так как текущая локаль может влиять на [0-9], поэтому она может быть не равна [0123456789], а чему-то другому.

...