У меня есть следующий шаблон в строке (IP-адрес):
123.444.888.235
Я хочу заменить последнее число после точки на 0
, чтобы оно стало:
123.444.888.0
Как я могу сделать это на bash
другом языке сценариев оболочки?
У меня есть следующий шаблон в строке (IP-адрес):
123.444.888.235
Я хочу заменить последнее число после точки на 0
, чтобы оно стало:
123.444.888.0
Как я могу сделать это на 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
без крайней левой части .
и того, что следует за ней.
${var%.*}
man bash
и нажмите ввод, затем введите /suffix pattern
и нажмите ввод. :)
new_var="${var%.*}.0"
... nJoy !.
Несколько способов (все они предполагают, что вы хотите изменить последний набор чисел в строке):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
Здесь, -F'.'
говорит awk
использовать .
в качестве разделителя поля ввода и -vOFS='.'
использовать его в качестве разделителя поля вывода. Тогда мы просто установить последнее поле ( $NF
) в 0 и напечатать строку ( 1;
это awk
сокращение для «печати текущей строки»).
$ 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-адресом, и вы заменяете последний октет этого адреса .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()
просто вычисляет битовое И для адреса и маску сети, чтобы получить сетевую часть адреса. Баш ожидает, что операнды &
будут целыми числами.Два вызова ipmask
показывают, как сеть может быть рассчитана по IP-адресу для двух разных масок.
Обратите внимание, как указано в вопросе, 123.444.888.235
это неверный IP-адрес. Я использовал 123.44.88.235
вместо этого для этих примеров.