Замініть рядок після останньої крапки в bash


12

У мене є такий рядок у рядку (IP-адреса):

123.444.888.235

Я хочу замінити останнє число після крапки на 0, так воно стає:

123.444.888.0

Як я можу це зробити на bashіншій мові сценарію оболонки?


1
Де ці струни? У баш-змінній? У текстовому файлі по одному на рядок?
Стефан Шазелас

Це в змінній. Мені шкода було забуто згадати про це.
Арі

3
Якщо це IP-адреси, то 444 і 888 є недійсними октетними значеннями.
Цифрова травма

Відповіді:


24

У будь-якій оболонці 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%.*}
голоси

@ tjt263, введіть командний рядок man bashі натисніть клавішу Enter, а потім введіть /suffix patternі натисніть клавішу Enter. :)
Wildcard

Додано кілька цитат після вашого допису : new_var="${var%.*}.0"... nJoy !.

8

Це має спрацювати.

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

Зауважимо, що останнє поле sedпідстановки, \10- це перший узгоджений шаблон ( \1), з'єднаний з буквальним нулем.


5

Кілька способів (всі вони припускають, що потрібно змінити останній набір чисел у рядку):

$ 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

5

Загальний випадок застосування мережевої маски до 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()просто обчислює біт І І адресу та мережну маску, щоб дати мережевій частині адреси. Баш очікує, що операнди &будуть цілими числами.

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


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


0

Альтернативна sedвідповідь:

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

Він групує все до останньої крапки і замінює повний рядок змістом групи з наступним 0.
Я використовую -r, щоб уникнути необхідності уникати дужок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.