Назад | Перейти на главную страницу

linux + сопоставить только VALID IP из текстового файла в другой файл

пожалуйста, посоветуйте, как сопоставить только действующие IP-адреса (255.255.255.255) из файла file.txt и вставить только действительный IP в файл VALID_IP.txt

решение должно быть реализовано в моем скрипте ksh (так что perl, sed или awk тоже подойдут)

больше file.txt

     e32)5.500.5.5*kjcdr
     ##@$1.1.1.1+++jmjh
     1.1.1.1333
     33331.1.1.1
     @5.5.5.??????
     ~3de.ede5.5.5.5
     1.1.1.13444r54
     192.9.30.174
     &&^#%5.5.5.5
     :5.5.5.5@%%^^&*
     :5.5.5.5:
     **22.22.22.22
     172.78.0.1()*5.4.3.277

пример файла VALID_IP.txt

     1.1.1.1
     192.9.30.174
     5.5.5.5
     5.5.5.5
     5.5.5.5
     22.22.22.22
     172.78.0.1

Следующее - подходящее регулярное выражение, разделенное на 4 разные строки ради моего рассудка.

(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.
(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.
(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.
(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])

Вывод:

egrep -o `cat regex` infile #all regex lines above joined, no spaces

1.1.1.1
1.1.1.133
31.1.1.1
5.5.5.5
1.1.1.134
192.9.30.174
5.5.5.5
5.5.5.5
5.5.5.5
22.22.22.22
172.78.0.1
5.4.3.27

Очевидно, это не соответствует вашему примеру. Зачем? Потому что мы не можем сказать, что тройка не принадлежит единице. Как видите, невозможно точно угадать количество мусора.

Это немного чище с perl

#!/usr/bin/perl
use Regexp::Common qw/net/;
while (<>) {
      print $1, "\n" if /($RE{net}{IPv4})/;
}

но он все равно получает ложные срабатывания

1.1.1.1
1.1.1.133
31.1.1.1
5.5.5.5
1.1.1.134
192.9.30.174
5.5.5.5
5.5.5.5
5.5.5.5
22.22.22.22
172.78.0.1

Perl один лайнер

perl -e 'use Regexp::Common qw/net/;while (<>) {print $1, "\n" if /($RE{net}{IPv4})/;}' infile

Я рекомендую использовать проверку диапазона вместо волосатых регулярных выражений. Вы можете сделать это в ksh без использования внешней утилиты или другого языка. Хотя решение Иана хорошее, это не основной модуль.

Вот чистый кш. Нет необходимости делать его однострочным, просто используйте функцию. Такой код легче понять, легче проверить на правильность и проще поддерживать.

#!/usr/bin/ksh
validate_ip () {
    typeset ip=$@
    typeset IFS=. valid=1
    typeset octets=($ip) octet
    typeset digits='^[[:digit:]]+$'

    if (( ${#octets[@]} == 4 ))
    then
        for ((octet = 0; octet <= 3; octet++))
        do
            value=${octets[octet]}
            if [[ ! "$value" =~ $digits ]] || ((value < 0 || value > 255))
            then
                valid=0
            fi
        done
    else
        valid=0
    fi

    if ((valid))
    then
        printf '%s\n' "$ip"
    fi

    return $valid
}

while read -r line
do
    validate_ip "$line"
done #< file.txt > VALID_IP.txt

Это ksh 93, я не тестировал его в ksh 88. Он также работает без изменений в Bash 3.2 или выше.