У меня есть следующий шаблон в строке (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вместо этого для этих примеров.