Заменить строку после последней точки в bash

У меня есть следующий шаблон в строке (IP-адрес):

123.444.888.235 

Я хочу заменить последнее число после точки на 0 , так что это будет:

 123.444.888.0 

Как я могу сделать это в bash или другом языке сценариев оболочки?

  • Ошибка скрипта Bash со строками с путями с пробелами и подстановочными знаками
  • Разделение строки на первое вхождение разделителя
  • Как правильно это перечислить с помощью инструментов Unix для pdfjam?
  • Как сохранить путь, построенный с помощью подстановочных знаков и содержащий пробелы в переменной
  • как удалить случайно созданные «~» и «..»
  • Командная строка (PS1), включая количество файлов в каталоге (как скрытых, так и обычных)
  • Как создать дерево процессов?
  • Выполнение команды внутри переменной не работает для sed
  • 5 Solutions collect form web for “Заменить строку после последней точки в bash”

    В любой оболочке POSIX:

     var=123.444.888.235 new_var="${var%.*}.0" 

    ${var%pattern} – это оператор, введенный ksh в 80-х годах, стандартизованный POSIX для стандартного языка sh и теперь реализованный всеми оболочками, которые интерпретируют этот язык, включая bash .

    ${var%pattern} расширяется до содержимого $var лишенного самой короткой строки, которая соответствует шаблону с конца (или равна $var если этот шаблон не совпадает). Таким образом, ${var%.*} (Где .* – это шаблон, который означает точку, за которой следует любое количество символов), расширяется до $var без права . и что следует за ним. В отличие от этого, ${var%%.*} Где самая длинная строка, соответствующая шаблону, разделяется, будет расширяться до $var без самой левой . и что следует за ним.

    Это должно сработать.

     echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/' 

    Обратите внимание, что последнее поле подстановки sed , \10 , является первым сопоставленным шаблоном ( \1 ), объединенным с литеральным нулем.

    Несколько способов (все это предполагает, что вы хотите изменить последний набор чисел в строке):

     $ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;' 123.444.888.0 

    Здесь, -F'.' говорит awk для использования . как разделитель полей ввода и -vOFS='.' использовать его как разделитель выходного поля. Затем мы просто устанавливаем последнее поле ( $NF ) равным 0 и печатаем строку ( 1; – сокращенно awk для «print the current line»).

     $ echo 123.444.888.235 | perl -pe 's/\d+$/0/' 123.444.888.0 

    -p указывает perl на печать каждой строки ввода после применения сценария, заданного -e . Сам скрипт – просто простой оператор замещения, который заменит одно или несколько чисел в конце строки на 0 .

     $ echo 123.444.888.235 | sed 's/[0-9]*$/0/' 123.444.888.0 

    Та же идея в sed , используя [0-9] вместо \d .


    Если ваша строка находится в переменной, и вы используете оболочку, которая поддерживает здесь строки (например, bash или zsh например), вы можете изменить выше:

     awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var perl -pe 's/\d+$/0/' <<<$var sed 's/[0-9]*$/0/' <<<$var 

    Общий случай применения сетевой маски к IP-адресу:

    Учитывая, что ваш вход является IP-адресом и что вы заменяете последний октет этого адреса на .0 , я предполагаю, что вы действительно пытаетесь достичь, это вычислить сетевую часть IP-адреса, используя 255.255.255.0 маска подсети.

    Просто замена октетов нулями в порядке, если длина вашей сетевой маски делится на 8, но это не общий случай. Если вам когда-либо понадобится выполнить эту операцию для любой действительной (подсети) сетевой маски, вы можете сделать что-то вроде этого:

     function d2i() { echo $(( 0x$( printf "%02x" ${1//./ } ) )) } function i2d() { h=$( printf "%08X" "$1" ) echo $(( 0x${h:0:2} )).$(( 0x${h:2:2} )).$(( 0x${h:4:2} )).$(( 0x${h:6:2} )) } function ipmask() { i2d $(( $( d2i $1 ) & $( d2i $2 ) )) } ipmask 123.44.88.235 255.255.255.0 # outputs 123.44.88.0 ipmask 123.44.88.235 255.255.255.240 # outputs 123.44.88.224 

    Это определяет 3 функции:

    • d2i() преобразует точечно-десятичную форму IP-адреса (или маски) в простое целое число
    • i2d() делает обратное – преобразует простое целое число в десятичную запятую
    • ipmask() просто вычисляет побитовое И адреса и сетевую маску для предоставления сетевой части адреса. Bash ожидает, что операнды & будут целыми числами.

    Два вызова ipmask показывают, как сеть может быть рассчитана с IP-адреса для двух разных масок.


    Примечание, как указано в вопросе, 123.444.888.235 является недопустимым IP-адресом. Я использовал 123.44.88.235 вместо этих примеров.

    Альтернативный ответ sed :

     sed -r 's/(.*\.).*/\10/' 

    Он группирует все до последней точки и заменяет полную строку содержимым группы, а затем 0.
    Я использую -r, чтобы избежать столкновения с круглыми скобками.

    Linux и Unix - лучшая ОС в мире.