LINUX.ORG.RU

AWK функция в BASH

 , ,


0

1

Друзья! Помогите. Я не программист, так, пишу посильные прикладные скрипты для себя. Возникла необходимость проверки IP адреса в скрипте. Накомпилил из сети функцию (c awk незнаком):

TEST_IP () {
echo $1 | awk -F "." '{if ( NF != 4 ) print "Ввод не является IP адресом";
else if ( $1 > 0 && $1 < 255 && $2 >=0 && $2 < 255 && $3 >=0 && $3 < 255 && $4 > 0 && $4 < 255 ) print "Валидный IP адрес";
else print "Невалидный IP адрес"}'
}


Не могу разобраться, есть ли возможность, вместе с сообщениями:
<print "Ввод не является IP адресом">; <print "Невалидный IP адрес">, возвращать код ошибки 1, как бы exit 1,
а вместе с сообщением <print "Валидный IP адрес"> - возвращать exit 0?
Т.е. другими словами, что бы функция на if else и else выдавала определенный мной код завершения?
Заранее спасибо!

Ответ на: комментарий от mky

Но это выводит из общего выражения {} Пожалуйста, приведите ваш пример в целиком функции, не в одной строчке. Вставьте ее в мой пример. А то я получаю от баша «syntax error» Спасибо!

Pashtet
() автор топика

Ну в общем вот тут нормально это описывают:

https://stackoverflow.com/questions/9708028/awk-return-value-to-shell-script

Если коротко, то «You can use exit to return an error code, but in general you can't modify the shell environment from a subprocess.»

Можно конечно поковыряться с переменными. Но почему бы не использовать какой-нибудь перл для этой задачи? Ну и было бы более полное описание задачи в конечном виде - было бы проще что-то подсказать

Kronick
()

Я упростил бы AWK-функцию:

TEST_IP () {
    echo $1 | awk -F "." '{
        if ( NF == 4 &&
             $1 > 0 && $1 < 255 &&
             $2 >=0 && $2 < 255 &&
             $3 >=0 && $3 < 255 &&
             $4 > 0 && $4 < 255 ) print 1
        else print 0
    }'
}

И использовал бы так:

if [ $(TEST_IP 1.1.1.1) -eq 1 ]
then
    echo "Валидный IP адрес"
else
    echo "Невалидный IP адрес"
fi


if [ $(TEST_IP blah.blah) -eq 0 ]
then
    echo "Невалидный IP адрес"
else
    echo "Валидный IP адрес"
fi

evbogdanov
()
Ответ на: комментарий от Pashtet
TEST_IP () {
echo $1 | awk -F "." '{
    if ( NF != 4 ) {
        print "Ввод не является IP адресом";
        exit 1;
    }
    else if ( $1 > 0 && $1 < 255 &&
              $2 >=0 && $2 < 255 &&
              $3 >=0 && $3 < 255 &&
              $4 > 0 && $4 < 255 ) {
        print "Валидный IP адрес";
        exit 0;
    }
    else {
        print "Невалидный IP адрес"
        exit 1;
    }
}'
}
legolegs ★★★★★
()
Ответ на: комментарий от evbogdanov

Я упростил бы AWK-функцию:

Удивительно, но у ТС-а была более правильная идея. Код возврата куда более эффективнее, чем чтение из пайпа по определению.

vodz ★★★★★
()
Ответ на: комментарий от legolegs
ARG0=$0

tst_0_255() {
    case "$1" in
    "" | *[![:digit:]]* ) return 1;;
    esac
    [ "$1" -gt 255 ] && return 1
    return 0
}

tst_IP() {
        local i
        local -a ip
        IFS=. read -ra ip <<< "$1"
        for((i=0;i<4;i++)); do
                tst_0_255 "${ip[i]}" || break
        done
        if [[ -n "${ip[i]}" || $i -ne 4 ]]; then
                echo "$ARG0: '$1' invalid, need like as 1.2.3.4" 1>&2
                return 1
        fi
        return 0
}
vodz ★★★★★
()
Ответ на: комментарий от vodz

Не соответствует ТЗ, у топикстартена первый и последний октеты не должны быть нулевыми.

Правильные адреса:

127.0.0.1
8.8.8.8
192.168.0.1
254.254.254.254
192.168.100.100

Неправильные:

0.0.0.0
127.0.0.0
10.20.30.400
0.1.2.3
192.168.zero.1
192.168.0.1.2

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Не соответствует ТЗ, у топикстартена первый и последний октеты не должны быть нулевыми.

Ну это принимается, только если оплата была назначена.

Впрочем, так и быть:

#!/bin/bash

ARG0=$0
tst_IP() {
        local i
        local -a ip
        IFS=. read -ra ip <<< "$1"
        for((i=0;;i++)); do
                case "${ip[i]}" in
                "") [[ $i -eq 4 ]] && return 0 || break;;
                *[![:digit:]]*) break;;
                esac
                [[ ${ip[i]} -gt 255 || $i -eq 4 ]] && break
                [[ ${ip[i]} -eq 0 && ( $i -eq 0 || $i -eq 3 ) ]] && break
        done
        echo "$ARG0: '$1' invalid, need like as 1.2.3.4" 1>&2
        return 1
}

vodz ★★★★★
()
Ответ на: комментарий от legolegs

192.168.zero.1

10.20.30.400

192.168.0.1.2

Не являются ip-адресами, в отличии от остальных «неправильных» примеров.

Ip0 ★★★★
()
Ответ на: комментарий от takino

да, я как-то так и думал, что там криво написано, взята строка откуда не помню, но не важно, тс-у то всё равно надо по русски.

Ну и инвалиду же надо артикль, так что перевели тоже так себе.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от lovesan

sudo apt-get install libdata-validate-ip-perl

А чего не на яве то?

vodz ★★★★★
()
Ответ на: комментарий от vodz
0.0.0.0/8           "This" Network             RFC 1122, Section 3.2.1.3

Опуская спецификацию «валидности» ввиду reserved ренжей, это вполне себе ip адрес

Ip0 ★★★★
()
Последнее исправление: Ip0 (всего исправлений: 1)
Ответ на: комментарий от Ip0

Опуская спецификацию «валидности» ввиду reserved ренжей, это вполне себе ip адрес

Речь была о смысле, а не о резервности. Ноль с любой маской даёт ноль и потому резервирование сети 0/8, как ни вкусна была б эта маска, — получается само собой по правилу битовой арифметики, а не по красивости адреса.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Ноль с любой маской даёт ноль и потому резервирование сети 0/8, как ни вкусна была б эта маска, — получается само собой по правилу битовой арифметики, а не по красивости адреса

????

IP адрес это просто 32 битное число (от 0 до 2^32-1). Нотация для удобства разбита на октеты. Конечно, 0.1.2.3 - это валидное число из этого ренжа (66051 в десятичной системе измерения).

Какой-нибудь 33.150.31.0 - так вообще может вполне себе валидным реальным адресом вполне конкретного конечно устройства. Не понимаю о чем ты говоришь.

Ip0 ★★★★
()
Ответ на: комментарий от Ip0

Не понимаю о чем ты говоришь.

Раз не понимаете, то и нефиг так возмущаться.

IP адрес это просто 32 битное число

Нет. Чтобы это «просто число» можно было б заюзать не только для некого числа, а для доставки пакетов в сети, надо, чтобы можно было вычислять интерфейс по адресу сети, на которую пакеты должны маршрутизироваться. Сеть вычисляется путем накладывания (отсортированной) маски на испытываемой адрес и адреса интерфейса. Полученные два числа сравниваются, если они одинаковые, то значить маршрутизировать — сюда. 0 даёт конфликт сравнения, ибо 0 одновременно будет означать либо не равно либо равно для сети 0/8. Потому единственно юзабелен только один маршрут с маской 0/0 как последний из отсортированных. Для 255/8 рассуждения похожи.

Какой-нибудь 33.150.31.0 - так вообще может вполне себе валидным реальным адресом

Конечно. Но такие адреса имеют изъян: такой адрес можно заюзать либо имея сразу сеть >= /23, либо /32. А вот поделить /23 до 24-30 уже не получится.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.