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