Как разбить строку по третьему разделителю .(точка)

Я полагаю, что где-то есть инструмент, который делает то, что вам нужно (недостаточно хорошо -известно ).

Однако в Linux и современных системах в стиле Unix -хранилище управляется с помощью диспетчера томов, LVM , обычно в Linux. После того, как это настроено, и большинство установщиков Linux знают, как это сделать, вы можете изменять размер томов во время выполнения -без перезагрузки. Поскольку управление томами в LVM очень простое, нет особого смысла тратить время и силы на другие подходы...

7
09.09.2019, 17:38
3 ответа

Используется sedнапример:

$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110

Пояснение:

sed s/search/replace/xищет строку и заменяет вторую. xопределяет, какое вхождение заменить -здесь 3-м. Часто gиспользуется вместо xдля обозначения всех вхождений.

Здесь мы хотим заменить точку ., но это специальный символ регулярного выражения sed, ожидаемый в термине search. Поэтому мы используем обратную косую черту от .до \., чтобы указать литерал ..

Поскольку мы используем здесь специальные символы в аргументе sed(, обратную косую черту\)нам нужно поместить весь аргумент в одинарные кавычки ''. Многие люди всегда используют здесь кавычки, чтобы не столкнуться с проблемами при использовании символов, которые могут быть специфическими для оболочки (, например пробел).

34
27.01.2020, 20:13

В этом случае третий также является последним. Если вы можете с уверенностью предположить, что вам всегда нужно менять последний ., вы можете сделать:

$ echo 'version: 1.8.0.110' | sed 's/\.\([^.]*\)$/-\1/'
version: 1.8.0-110

или, если ваш sedподдерживает -E(, большинство делает )с:

$ echo 'version: 1.8.0.110' | sed -E 's/\.([^.]*)$/-\1/'
version: 1.8.0-110

Это будет искать ., а затем 0 или более не-.символов([^.])до конца строки($). Поскольку [^.]*находится в круглых скобках (\( \)), он «захвачен» и может упоминаться как \1в правой части оператора замены. Таким образом, это заменит символы .и не -.после него на -и эти символы.


Если это должен быть третий, а не последний, @Ned64 уже дал самый простой подход , но в качестве альтернативы вы могли бы:

$ echo 'version: 1.8.0.110' | perl -pe 's/(([^.]+\.){2}[^.]+)\./$1-/'
version: 1.8.0-110
2
27.01.2020, 20:13

Использовать bash

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

Предположим, что у вас есть

vers='version: 1.8.0.110'

ответ прост:

$ echo ${vers%.*}-${vers##*.}
1.8.0-110

% означает удаление самой короткой совпадающей строки справа. ##означает удаление самой длинной строки слева, которая соответствует.

Что делать, если периодов больше трех?

Если вы действительно хотите заменить третий период, а не последний период, как я предположил выше, в bash это становится немного сложнее, но это все же возможно. Например, если vers='version: 1.8.0.110.hut.hut.hut.hike!', вы можете найти все после третьей точки и использовать это для усечения строки:

$ end=${vers#*.*.*.}
$ start=${vers%$end}
$ echo ${start%.}-$end
version: 1.8.0-110.hut.hut.hut.hike!

Другой способ :использования IFS для разбиения строки на массив bash

Хотя это излишне для вопроса, иногда полезно разделить строку на компоненты и загрузить их в массив.

IFS=. read -a foo <<<'version: 1.8.0.110.hut.hut.hut.hike!'

Вы можете просмотреть массив $fooи выбрать, что и когда печатать. Например,

echo -n $foo
for ((i=1; i<${foo[@]}; i++)); do 
  [[ i -eq 3 ]] && echo -n - || echo -n.
  echo -n ${foo[i]};
done
echo
5
27.01.2020, 20:13

Теги

Похожие вопросы