У мене є такий рядок у рядку (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
і натисніть клавішу Enter, а потім введіть /suffix pattern
і натисніть клавішу Enter. :)
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
замість цих прикладів.