IP адрес или нет?


25

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

Адрес IPv4 - это 32-разрядный числовой адрес, записанный в виде четырех чисел, разделенных точками. Каждое число может быть от нуля до 255 .

Нам нужно написать инструмент для предварительной проверки ввода, чтобы избежать этих сбоев, и наш конкретный инструмент требователен: допустимый формат будет выглядеть так, a.b.c.dгде a, b, c и d:

  • Может быть 0или натуральным числом без начальных нулей .
  • Должно быть между 0 - 255 (включительно).
  • Если не содержат специальные символы , такие как +, -, ,и другие.
  • Должен быть десятичным (базовым 10)

Ввод : строка

Вывод : значение «истина» или «ложь» (произвольные значения также принимаются)

Тестовые случаи :

Input            |  Output  |  Reason
                 |          |
- 1.160.10.240   |  true    |
- 192.001.32.47  |  false   |  (leading zeros present)
- 1.2.3.         |  false   |  (only three digits)
- 1.2.3          |  false   |  (only three digits)
- 0.00.10.255    |  false   |  (leading zeros present)
- 1.2.$.4        |  false   |  (only three digits and a special symbol present)
- 255.160.0.34   |  true    |
- .1.1.1         |  false   |  (only three digits)
- 1..1.1.1       |  false   |  (more than three periods)
- 1.1.1.-0       |  false   |  (special symbol present)
- .1.1.+1        |  false   |  (special symbol present)
- 1 1 1 1        |  false   |  (no periods)
- 1              |  false   |  (only one digit)
- 10.300.4.0     |  false   |  (value over 255)
- 10.4F.10.99    |  false   |  (invalid characters)
- fruit loops    |  false   |  (umm...)
- 1.2.3.4.5      |  false   |  (too many periods/numbers)
- 0.0.0.0        |  true    |
- 0.0 0.0.       |  false   |  (periods misplaced)
- 1.23..4        |  false   |  (a typo of 1.2.3.4)
- 1:1:1:1:1:1:1:1|  false   |  (an IPv6 address, not IPv4)

Это , поэтому выиграет меньше байтов!

Примечание для пользователей - если вы хотите добавить еще несколько тест-кейсов, добро пожаловать (предлагая редактирование). Но, пожалуйста, убедитесь, что тесты не повторяются! Благодарность


10
Предлагайте testcases: 1.1.1.1.1, 1.1.1.1., .1.1.1, 1..1.1, 1..1.1.1, 1.1.1.0, 1.1.1.-0, 1.1.1.+1, 1.1.1.1E1, 1.1.1.256, 1.1.1.0x1, 255.255.255.255, 0.0.0.0, 'or 1=1--, <empty string>, 1 1 1 1, 1,1,1,1.
Чт

5
Предложите добавить тестовые случаи "1.2.3.4.5" (чтобы исключить слишком длинные IP-адреса) и "999.0.0.0" (чтобы исключить слишком большие IP-адреса).
Триггонометрия

5
Возможно, слегка требователен, но вы, вероятно, должны ссылаться на «адреса IPv4», а не на «IP-адреса» - или, по крайней мере, упомянуть где-то, что вы просто имеете в виду адреса IPv4 - в противном случае 1234: 5678 :: 1 должен быть действительным IP-адресом (тогда как Из описания видно, что это не предназначено :)
psmears

3
@Criggie Идея состоит не в том, чтобы на самом деле проверить все настоящие правила IP4 (например, те, которые вы упомянули), а в том, чтобы убедиться, что входная строка не вызывает сбой в каком-либо другом (предположительно, плохо написанном) приложении, которое допускает ввод только в очень определенной форме. , Кроме того, мы не собираемся менять правила задания, на которое уже есть более 30 ответов.
BradC

2
@Criggie Стоит отметить, что RFC объявляет, что «Адреса имеют фиксированную длину в четыре октета». Я думаю, что крайние случаи, на которые вы ссылаетесь, более специализированы, чем этот вызов.
Тыкай

Ответы:


26

Машинный код X86_64: 18 16 байт

Изменить: этот ответ не совсем работает, так как

  1. я использую inet_pton из стандартных библиотек C, что означает, что мне нужно extern. Я не включил extern в мой счетчик байтов.
  2. В результате я использовал красную зону для фактического адреса, но вызвал функцию, которая также могла бы использовать красную зону. К счастью, его нет на моей машине, но некоторые странные стандартные библиотеки могут использовать его, что может привести к неопределенному поведению.

И да, все это в значительной степени делается уже написанной функцией

Во всяком случае, это то, что я получил: 48 89 fe 6a 02 5f 48 8d 54 24 80 e9 00 00 00 00

Монтаж:

section .text
    extern inet_pton
    global ipIsValid

ipIsValid:
    mov rsi, rdi
    ;mov rdi, 2 ; change to 10 for ipv6
    push 2
    pop rdi ; thank you peter
    lea rdx, [rsp - 128]
    jmp inet_pton

Объяснение:

Посмотрите на inet_pton(3). Он берет строковый IP-адрес и помещает его в буфер, который вы можете использовать struct sockaddr. Он принимает 3 аргумента: семейство адресов ( AF_INET(ipv4), 2 или AF_INET6(ipv6), 10), строку адреса ip и указатель на вывод. Он возвращает 1 в случае успеха, 0 для недопустимого адреса или -1 в случае, когда семейство адресов отсутствует AF_INETили AF_INET6(что никогда не произойдет, потому что я передаю ему константу).

Поэтому я просто перемещаю строку в регистр для второго аргумента, устанавливаю первый регистр в 2 и устанавливаю третий регистр в красную зону (128 байтов ниже указателя стека), так как мне плевать на результат. Тогда я могу просто jmpк inet_ptonи пусть , что возвращение прямо к абоненту!

Я включил эту программу быстрого тестирования, чтобы проверить ваши случаи:

#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ip.h>

extern int ipIsValid(char *);

int main(){
    char *addresses[] = {
        "1.160.10.240",
        "192.001.32.47",
        "1.2.3.",
        "1.2.3",
        "0.00.10.255",
        "1.2.$.4",
        "255.160.0.34",
        ".1.1.1",
        "1..1.1.1",
        "1.1.1.-0",
        ".1.1.+1",
        "1 1 1 1",
        "1",
        "10.300.4.0",
        "10.4F.10.99",
        "fruit loops",
        "1.2.3.4.5",
        NULL
    };

    for(size_t i = 0; addresses[i] != NULL; ++i){
        printf("Address %s:\t%s\n", addresses[i],
            ipIsValid(addresses[i]) ? "true" : "false");
    }
    return 0;
}

Соберите с nasm -felf64 assembly.asm, скомпилируйте gcc -no-pie test.c assembly.o, и вы получите:

Address 1.160.10.240:   true
Address 192.001.32.47:  false
Address 1.2.3.: false
Address 1.2.3:  false
Address 0.00.10.255:    false
Address 1.2.$.4:    false
Address 255.160.0.34:   true
Address .1.1.1: false
Address 1..1.1.1:   false
Address 1.1.1.-0:   false
Address .1.1.+1:    false
Address 1 1 1 1:    false
Address 1:  false
Address 10.300.4.0: false
Address 10.4F.10.99:    false
Address fruit loops:    false
Address 1.2.3.4.5:  false

Я мог бы сделать это намного меньше, если бы вызывающий должен был передать AF_INETили AF_INET6функцию


4
Мне нравится, что ты сделал это в ассм. И тот факт, что вы объяснили это тем, кто может не понять этого (а также тестировать код), еще лучше. Что не означает, что я мог бы сделать это в ассм; прошло слишком много лет, но я помню достаточно, чтобы точно понять, что говорит (делает) ваше объяснение (и, следовательно, процесс). Хорошая работа.
Прифтан

4
e9 00 00 00 00это jmp near $+5, а не jmp inet_pton. Если вы предоставляете код операции, вы должны включить включающую inet_ptonчасть, а не оставлять пустым
l4m2


3
Вы должны включить extern в заголовок ответа, так как программа требует его, и он доступен не на всех платформах.
QWR

1
«mov rdi, 2» может быть «push 2 / pop rdi» для -2 байтов. Также обратите внимание, что разборка неправильная или код неправильный. Это либо "mov edi" (не rdi), либо отсутствует префикс.
Питер Ферри

13

Java (JDK) , 63 байта

s->("."+s).matches("(\\.(25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)){4}")

Попробуйте онлайн!

кредиты


Вы забыли удалить конечную точку с запятой. ;) И я могу убедиться, что это работает для всех тестовых случаев, в том числе в комментариях. Посмотрим, увижу ли я кое-что в гольфе.
Кевин Круйссен

3
Не удалось.1.2.3.4
l4m2

Разрешено ли использовать логическое значение, когда явно требуется 0/1?
14 м2 18

1
@ l4m2 Первоначальный вопрос был действительным / недействительным. Таким образом, я предполагаю, что любое истинное / ложное значение здесь приемлемо.
Кевин Круйссен

Output: 0 or 1и у Java нет автоматического bool-> int
l4m2

12

JavaScript (Node.js) , 43 байта

x=>x.split`.`.map(t=>[t&255]==t&&[])==`,,,`

Попробуйте онлайн!

JavaScript (Node.js) , 46 байт

x=>x.split`.`.every(t=>k--&&[t&255]==t,k=4)*!k

Попробуйте онлайн!

часть Арно

JavaScript (Node.js) , 54 53 51 байт

x=>x.split`.`.every(t=>k--*0+t<256&[~~t]==t,k=4)*!k

Попробуйте онлайн!

-2B для 0+t<256, -1B от Патрика Стефансена, + 1B, чтобы избежать ввода1.1.1.1e-80

Решение RegExp 58 54 байта

s=>/^((2(?!5?[6-9])|1|(?!0\d))\d\d?\.?\b){4}$/.test(s)

Спасибо Deadcode за 3 байта


Я добавил несколько тестовых случаев!
RC7


1
@KevinCruijssen 0.0.0.0здесь правда. Почему SQL-инъекция здесь?
14 м2 18

Ах, подождите, я неверно истолковал предложение в описании вызова. 0.0.0.0это действительно правда. Это также повлияет на мой ответ .. (И что вы подразумеваете под SQL-инъекцией?: S Ссылка на TIO со ВСЕМИ тестовыми случаями.)
Кевин Круйссен

1
@ l4m2 Я добавил его, так как нам нужны тестовые примеры, которые даже не похожи на IP-адрес.
Чт

11

PHP , 39 36 байт

<?=+!!filter_var($argv[1],275,5**9);

Попробуйте онлайн!

275 напоминает постоянную FILTER_VALIDATE_IP

5 ** 9 используется вместо константы FILTER_FLAG_IPV4. Этого достаточно, потому что5**9 & FILTER_FLAG_IPV4 это правда, что именно то, что PHP делает в фоновом режиме, как отметил Бенуа Эснард.

Здесь filter_varвозвращает первый аргумент, если это действительный адрес IPv4, или false, если это не так. С помощью +!!мы производим выходные данные, необходимые для вызова.


3
Здесь используется 5**9вместо 1048576сохранения 3 байта: PHP использует &для проверки флагов IPv4 / IPv6 , поэтому допустимо любое число от 1048576 до 2097151.
Бенуа Эснард

Настоящим я опускаю ваш ответ за (в основном) мой ответ: codegolf.stackexchange.com/a/174470/14732, который был написан в 2018-10-22 09: 17: 34UTC, в то время как ваш был написан в 2018-10-22 09: 21: 55UTC. Даже если я верну 1-байтовую оптимизацию, заданную @BenoitEsnard, мой ответ точно такой же, как и ваш по функциональности.
Исмаэль Мигель

2
Я должен извиниться, я не видел вашего ответа, хотя в то время, когда я его писал, в PHP не было представления по этому вопросу (как вы сказали, разница во времени составляет менее пяти минут).
октуполь

Я знаю, и я понимаю это. Я только заметил тебя только сейчас. Я могу откатить мой, а вы продолжите оптимизацию. Но я не знаю, отличает ли это ответ от другого.
Исмаэль Мигель

17
@IsmaelMiguel Я бы не стал никого за это опускать, если бы это было правдоподобно, если бы вы не начали, вас там не было. С 5-минутной разницей, это не только правдоподобно, это почти наверняка так, что очевидно, даже если автор сам так не говорит.
Дункан Х Симпсон

11

PHP, 36 байт

echo(ip2long($argv[1])===false?0:1);

ip2longэто хорошо известная встроенная функция .



Кажется, для этого используются функции без кодировки, присутствующие в более новых версиях (я предполагаю, что это из PHP7 +). Имейте в виду, что для PHP 4 и 5 это допускает неполные IP-адреса.
Исмаэль Мигель



1
Это даст успех, если вы передадите ему любое целое число, например 1, 2 и т. Д. Не думайте, что это следует делать. А также, если вы кормите это что-то как 100.100.100
-

10

Perl 6 , 22 21 20 байт

-1 байт благодаря Филу Х.

{?/^@(^256)**4%\.$/}

Попробуйте онлайн!

объяснение

{                  }  # Anonymous Block
  /               /   # Regex match
   ^             $    # Anchor to start/end
    @(    )           # Interpolate
      ^256            #   range 0..255,
                      #   effectively like (0|1|2|...|255)
           **4        # Repeated four times
              %\.     # Separated by dot
 ?                    # Convert match result to Bool

3
Чувак, мне нужно больше времени на выяснение регулярных выражений Perl 6. У меня не было никакого %модификатора. Интересно, пытается ли он проверить все 256**4возможности?
Джо Кинг

1
Вместо этого <{^256}>вы можете просто преобразовать диапазон в массив @(^256)за -1 символ TIO . Изменяя блок кода на массив, он также становится намного быстрее (0,4 с вместо 30).
Phil H

@PhilH Круто, спасибо. Я пытался, $(^256)но теперь я понимаю, почему это не сработало.
nwellnhof

9

05AB1E , 26 24 23 22 23 байта

'.¡©g4Q₅Ý®å`®1šDïþJsJQP

-1 байт благодаря @Emigna .
+1 байт для 1.1.1.1E1исправления ошибки в тесте, возвращающем неверный результат.

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

'.¡              '# Split the (implicit) input by "."
   ©              # Save it in the register (without popping)
    g4Q           # Check that there are exactly 4 numbers
    ₅Ý®å          # Check for each of the numbers that they are in the range [0,255],
        `         # and push the result for each number separated onto the stack
    ®1šDïþJsJQ    # Check that each number does NOT start with a "0" (excluding 0s itself),
                  # and that they consist of digits only
              P   # Check if all values on the stack are truthy (and output implicitly)

1
Вы должны быть в состоянии использовать Āвместо<d
Emigna

@MagicOctopusUrn Боюсь , он не для 1.1.1.1E1, 1..1.1.1, 1.1.1.1., 192.00.0.255, и 0.00.10.255. (PS: я исправил 1.1.1.1E1, добавив þпроверку на объединение и равенство.)
Кевин Круйссен

Достаточно справедливо, решил, что я что-то упустил.
Волшебная Урна Осьминога

@MagicOctopusUrn Основная проблема - 05AB1E, в которой числа с ведущими 0 равны тем, которые без, даже в виде строки. Вот почему я использую DïþJsJQпроверку, где ïприводим его к int, чтобы удалить начальные 0, и þоставляем только цифры, удаляя такие вещи, как E, -и т. Д. :) Это для тестового примера 0.00.10.255, так как 00010255и 0010255будет равно.
Кевин Круйссен

Да, я прошел через ту же самую чепуху, хотя смена всех чисел работала довольно хорошо, за исключением тех случаев. Интересно, когда функции, полезные для одних задач, становятся почти ошибочными для других.
Волшебная Урна Осьминога

6

PowerShell, 59 51 49 байт

-8 байт, спасибо @AdmBorkBork

-2 байта, trueили falseразрешено автором

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

Тестовый скрипт:

$f = {

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

}

@(
    ,("1.160.10.240" , $true)
    ,("192.001.32.47" , $false)
    ,("1.2.3." , $false)
    ,("1.2.3" , $false)
    ,("0.00.10.255" , $false)
    ,("192.168.1.1" , $true)
    ,("1.2.$.4" , $false)
    ,("255.160.0.34" , $true)
    ,(".1.1.1" , $false)
    ,("1..1.1.1" , $false)
    ,("1.1.1.-0" , $false)
    ,("1.1.1.+1" , $false)
    ,("1 1 1 1" , $false)
    ,("1"            ,$false)
    ,("10.300.4.0"   ,$false)
    ,("10.4F.10.99"  ,$false)
    ,("fruit loops"  ,$false)
    ,("1.2.3.4.5"    ,$false)

) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result : $s"
}

Выход:

True: True : 1.160.10.240
True: False : 192.001.32.47
True: False : 1.2.3.
True: False : 1.2.3
True: False : 0.00.10.255
True: True : 192.168.1.1
True: False : 1.2.$.4
True: True : 255.160.0.34
True: False : .1.1.1
True: False : 1..1.1.1
True: False : 1.1.1.-0
True: False : 1.1.1.+1
True: False : 1 1 1 1
True: False : 1
True: False : 10.300.4.0
True: False : 10.4F.10.99
True: False : fruit loops
True: False : 1.2.3.4.5

Объяснение:

Сценарий пытается проанализировать строку аргумента, чтобы создать объект .NET, IPAddress .

  • вернуть, $trueесли objectсоздан, и строка аргумента равна строковому представлению object(нормализованный адрес по object.toString())
  • вернуть $falseиначе

PowerShell, 59 56 54 байта, альтернатива «не использовать .NET lib»

-3 байта, trueили falseразрешено автором

-2 байта, спасибо @ Deadcode за классное регулярное выражение.

".$args"-match'^(\.(2(?!5?[6-9])|1|(?!0\B))\d\d?){4}$'

Попробуйте онлайн!

Спасибо Оливье Грегуар за оригинальное регулярное выражение.


1
Вам не нужно вызывать, |% t*gпоскольку PowerShell автоматически приведёт правую часть -eqстроки как строку, потому что левая часть - это строка. -try{+("$args"-eq[IPAddress]::Parse($args))}catch{0}
AdmBorkBork

Вы можете вырезать 2 байта из версии "not use .NET lib" с помощью моего регулярного выражения (адаптированного к методу вставки периода, который, конечно, не может быть в моей версии, потому что это чистый регулярный код): tio.run/…
Deadcode

5

C (gcc) / POSIX, 26 байтов

f(s){s=inet_pton(2,s,&s);}

Попробуйте онлайн!

Работает как 64-битный код на TIO, но, вероятно, требует этого sizeof(int) == sizeof(char*)на других платформах.


@TobySpeight Да, если вы используете x86, вам, вероятно, стоит попробовать в 32-битном режиме ( -m32).
nwellnhof

Я получил его на работу, передавая sкак char*(нет доступа к системе ILP32 здесь), и да, я смешивался inet_aton().
Тоби Спейт

5

PHP 7+, 37 35 32 байта

При этом используется встроенная функция filter_varдля проверки того, что это адрес IPv4 .

Чтобы это работало, вам нужно передать ключ iчерез запрос GET.

<?=filter_var($_GET[i],275,5**9);

Ничего не выводит (для falsyрезультата) или IP (для truthyрезультата), в зависимости от результата.

Вы можете примерить это на: http://sandbox.onlinephpfunctions.com/code/639c22281ea3ba753cf7431281486d8e6e66f68e http://sandbox.onlinephpfunctions.com/code/ff6aaeb2b2d0e0ac43f48125de0549320bc071b4


При этом используются следующие значения напрямую:

  • 275 = FILTER_VALIDATE_IP
  • 1 << 20 = 1048576 = FILTER_FLAG_IPV4
  • 5 ** 9 = 1953125 (который имеет требуемый бит как «1» для 1048576)

Спасибо Бенуа Эснарду за этот совет, который спас мне 1 байт!

Спасибо Титу за напоминание об изменениях в конкурсе.


Я рассмотрел использование этой функции ip2long, но она работает с неполными IP-адресами.

Неполные адреса IPv4 считаются недопустимыми в этом вызове.

Если бы они были разрешены, это был бы окончательный код (только для PHP 5.2.10):

<?=ip2long($_GET[i]);

В настоящее время в документации не указано, что это перестанет работать (при передаче неполного ip) с более новыми версиями PHP.

После тестирования подтвердил, что это так.

Спасибо nwellnhof за отзыв!


Здесь используется 5**9вместо 1<<20сохранения один байт: PHP использует &для проверки флагов IPv4 / IPv6 , поэтому допустимо любое число от 1048576 до 2097151.
Бенуа Эснард

В новых версиях PHP ip2longне допускает неполных адресов.
nwellnhof

@BenoitEsnard Спасибо! Я добавил это к ответу
Исмаэль Мигель

@nwellnhof После тестирования я подтверждаю, что это так. Тем не менее, я не думаю, что это хорошая идея, так как это явно не задокументировано.
Исмаэль Мигель

+!!не требуется; ОП теперь принимает произвольные истинные значения.
Тит

5

Python 3: 81 78 70 69 66 байт

['%d.%d.%d.%d'%(*x.to_bytes(4,'big'),)for x in range(16**8)].count

Переберите все возможные адреса IPv4, получите строковое представление и сравните его с входными данными. Эээээээ ... Бегает некоторое время.

РЕДАКТИРОВАТЬ: Удалено 3 байта путем перехода от полной программы к анонимной функции.

EDIT2: удалено 8 байт с помощью xnor

EDIT3: удален 1 байт с использованием распакованной карты вместо понимания списка

EDIT4: удалены 3 байта, используя понимание списка вместо ipaddressмодуля


2
Я думаю, что ваша анонимная функция может быть просто [str(ip_address(x))for x in range(256**4)].count. Также 256**4может быть 16**8.
xnor

5

C # (интерактивный компилятор Visual C #) , 84 79 65 байт

s=>s.Split('.').Sum(t=>byte.TryParse(t,out var b)&t==b+""?1:5)==4

Попробуйте онлайн!

-5 и -14 байтов сохранено благодаря @dana!

# C # (интерактивный компилятор Visual C #) , 61 байт

s=>s.Count(c=>c==46)==3&IPAddress.TryParse(s,out IPAddress i)

Попробуйте онлайн!

Работа в процессе. Используйте код System.Net(+17 байт, если вы считаете его). если вам интересно почему я считаю и разбираю

Ограничение метода IPAddress.TryParse заключается в том, что он проверяет, может ли строка быть преобразована в IP-адрес, и, таким образом, если ей передается строковое значение, например «5», он считает его «0.0.0.5».

источник

Как сказал @milk в комментарии, он действительно не справится с ведущими нулями. Итак, 61 байт один не работает.


1
@ Дана отлично. Красиво сделано! Еще четыре, и это побьет 61-байтовое решение!
Aloisdg говорит восстановить Монику

4

Python 2 , 85 82 81 байт

-1 байт благодаря Кевину Круйссену

from ipaddress import*
I=input()
try:r=I==str(IPv4Address(I))
except:r=0
print~~r

Попробуйте онлайн!

113-байтовый ответ удаляется, так как1.1.1.1e-80


1
Вы можете играть print 1*rв гольф на print~~r. +1, хотя, так как, кажется, работает для всех возможных тестовых случаев, предложенных до сих пор . PS: Ваш 113-байтовый ответ не подходит для 1.1.1.1e-80.
Кевин Круйссен

@KevinCruijssen Спасибо! Не думал о такой записи чисел
Мертвый Опоссум

Разве это не ipaddressмодуль Python 3?
Farhan.K

@ Farhan.K Не знаю, но это работает в TIO
Мертвый Опоссум

4

Japt, 17 15 байт

q.
ʶ4«Uk#ÿòs)Ê

Попробуйте или выполните все контрольные примеры или проверьте дополнительные контрольные примеры из комментариев


объяснение

Мы разделяем массив на ., проверяем, что длина этого массива равна 4AND, что длина, когда ["0","255"]из него удаляются все элементы в диапазоне , равна falsey ( 0).

                 :Implicit input of string U
q.               :Split on "."
\n               :Reassign resulting array to U
Ê                :Length of U
 ¶4              :Equals 4?
   «             :&&!
    Uk           :Remove from U
      #ÿ         :  255
        ò        :  Range [0,255]
         s       :  Convert each to a string
          )      :End removal
           Ê     :Length of resulting array

Хороший ответ. Также проверено для всех предложенных тестовых случаев до сих пор . Любопытно увидеть это объяснение.
Кевин Круйссен

2
@KevinCruijssen, объяснение добавлено. Спасибо за эти дополнительные тесты.
лохматый

3

Mathematica, 39 31 байт

Оригинальная версия:

¬FailureQ[Interpreter["IPAddress"][#]]&

Модифицированная версия (спасибо Мише Лаврову)

 AtomQ@*Interpreter["IPAddress"]

который возвращает, Trueесли вход является действительным IP-адресом ( попробуйте ).

Если вы настаиваете на получении 1и 0вместо этого, тогда потребуются дополнительные 7 байтов:

Boole/@AtomQ@*Interpreter["IPAddress"]

Так как Interpreter["IPAddress"]возвращает строку для правильного ввода и некоторый сложный объект сбоя для неверного ввода, мы можем проверить на допустимые входы с помощью AtomQ[Interpreter["IPAddress"][#]]&, который может быть далее сокращен до композиции функции AtomQ@*Interpreter["IPAddress"]. Попробуйте онлайн!
Миша Лавров

Сбой на IPv6-адресе, как 2001:0db8:85a3:0000:0000:8a2e:0370:7334.
lirtosiast


3

Python 2, 93 89 67 53 байта

[i==`int(i)&255`for i in input().split('.')]!=[1]*4>_

Попробуйте онлайн!

Спасибо Деннису за бритье другого 14 байтов на внутренних сравнениях и коде выхода.

Отдельное спасибо Джонатану Аллану за бритье 22 байта и исправление логики! Надоедливая попытка / кроме никого!

Благодаря правильному форматированию строк вместо необработанных байтов, Джо Кинг сбрасывает 4 байта.


Ваш чек может быть в гольф i==`int(i)&255` . Кроме того, вы можете вызвать ошибку [...]!=[1]*4>_, так как вы все равно используете коды выхода. Попробуйте онлайн!
Денис

@ Денис, я не понимаю, что >_делает. Битовый и довольно гениальный, хотя ... Я не смог объединить их сам.
TemporalWolf

2
Если !=возвращается False, Python закорачивается и ничего не происходит; переводчик выходит нормально. Если он возвращает True, >_возникает ошибка NameError, потому что переменная _не определена.
Деннис

Рисунки, которые я сравниваю в своем ответе, а затем пропускаю очевидный результат в вашем комментарии. Спасибо за объяснение.
TemporalWolf

3

СФК , 176 байт

* изначально был Bash + SFK, но с тех пор TIO добавил правильную оболочку SFK

xex -i "_[lstart][1.3 digits].[1.3 digits].[1.3 digits].[1.3 digits][lend]_[part2]\n[part4]\n[part6]\n[part8]_" +xed _[lstart]0[digit]_999_ +hex +linelen +filt -+1 -+2 +linelen

Попробуйте онлайн!


Будет ли сначала проверка ошибки распечатки nc [addr] 1 -w1сократить это?

@Rogem ncпринимает как начальные нули, так и IPv6-адреса, поэтому мне все равно придется с ними справляться - и это все равно скорее sfkответ, чем ответ оболочки.
Οurous

3

python3 Bash * 60

* Также другие снаряды. Любой, для которого проверка на правдивость / ложность проходит код завершения программы

read I
python3 -c "from ipaddress import*;IPv4Address('$I')"

объяснение

Проблема с чисто Python-решениями заключается в том, что сбой программы считается неопределенным. Мы могли бы использовать «много» кода для преобразования исключения в правильное истинное значение. Однако в какой-то момент интерпретатор Python обрабатывает это необработанное исключение и возвращает ненулевой код завершения. Из-за низкой стоимости смены языков на вашу любимую оболочку Unix мы можем сэкономить немало кода!

Конечно, это уязвимо для инъекционных атак ... Входные данные, такие как, 1.1.1.1'); print('Doing Something Evilявляются прямой угрозой!


( Объяснение это (не объяснение ).)
Питер Мортенсен

@PeterMortensen Yikes. Это было даже подчеркнуто красным. Мой браузер пытался меня спасти, но я не слушал. Спасибо, что поймали это!
Сомпом

Полные программы позволили вывести через коды выхода, поэтому это может быть 43 байт .
მოიმო

@BMO Интересно. Спасибо что подметил это! Я думаю, что определение проблемы изменилось с "Truthy / Falsy" на разрешение произвольного вывода, так как я опубликовал это, но я мог просто не заметить раньше :)
Sompom

3

ECMAScript чистое регулярное выражение, 41 байт

^((2(?!5?[6-9])|1|(?!0\B))\d\d?\.?\b){4}$

Попробуйте онлайн!
Попробуйте это на regex101

Я думаю, что логика в этом регулярном выражении говорит сама за себя, поэтому я просто напечатаю, но не буду комментировать это:

^
(
    (
        2(?!5?[6-9])
    |
        1
    |
        (?!0\B)
    )
    \d\d?
    \.?\b
){4}
$

Это может быть использовано для сброса 2 байтов следующих ответов:

Вот альтернативная версия, которая допускает начальные нули, но делает это последовательно (октеты могут быть представлены максимум 3 десятичными цифрами):

^((2(?!5?[6-9])|1|0?)\d\d?\.?\b){4}$

Или разрешить любое количество ведущих нулей:

^(0*(2(?!5?[6-9])|1?)\d\d?\.?\b){4}$


1
\bи \B... это умно!
Маззи

1
@mazzy Да, эти два действительно пригодятся! Я мог бы использовать (?!0\d)вместо этого, но мне нравится \Bлучше!
Deadcode

Ответ PowerShell не становится короче с вашим регулярным выражением. Мне жаль. Кавычки необходимы для преобразования массива в строку. Попробуйте онлайн!
Маззи

1
\.?\bСпас меня байт на мой ответ тоже, спасибо!
Нил

1
Сохранено 3 байта thx
l4m2

2

Красный , 106 байт

func[s][if error? try[t: load s][return off]if 4 <> length? t[return off]s =
form as-ipv4 t/1 t/2 t/3 t/4]

Попробуйте онлайн!

Returnd true илиfalse

Объяснение:

f: func [ s ] [
    if error? try [                  ; checks if the execution of the next block result in an error
        t: load s                    ; loading a string separated by '.' gives a tuple   
    ] [                              ; each part of which must be in the range 0..255
        return off                   ; if there's an error, return 'false' 
    ]
    if 4 <> length? t [              ; if the tuple doesn't have exactly 4 parts
        return off                   ; return 'false'  
    ]
    s = form as-ipv4 t/1 t/2 t/3 t/4 ; is the input equal to its parts converted to an IP adress
]

2

Stax , 14 байт

∞n·Θ3ª&JH‼∙*~Γ

Запустите и отладьте его

Распакованный, размазанный и прокомментированный, это выглядит так.

VB      constant 256
r       [0 .. 255]
'|*     coerce and string-join with "|"; i.e. "0|1|2|3 ... 254|255"
:{      parenthesize to "(0|1|2|3 ... 254|255)"
]4*     make 4-length array of number pattern
.\.*    string join with "\\."; this forms the complete regex
|Q      is the input a complete match for the regex?

Запустите этот


Удивлен, узнав, что вы сделали язык Stax! это работает хорошо.
rv7

Благодарность! Пространство языков игры в гольф удивительно переполнено, и я не уверен, может ли stax оправдать свое существование по существу, но моей главной целью было просто посмотреть, смогу ли я это сделать и, возможно, чему-нибудь научиться. Это оказалось веселее, чем ожидалось.
рекурсивный

2

Python 3, 109 93 байта

import re
lambda x:bool(re.match(r'^((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(\.(?!$)|$)){4}$',x))

объяснение

Каждый октет может быть 0 - 255:

  • начинается с 25 и имеет 0-5 в качестве последней цифры
  • начинается с 2, имеет 0-4 в качестве второй цифры и любую цифру в конце
  • начинается с 1 и 00 - 99 как остальные цифры
  • имеет только 2 цифры - 1-9 является первой и любая последующая цифра
  • или просто одна цифра

Октет может заканчиваться символом (.) Или просто заканчиваться, при условии, что он не может сделать оба, отрицательный взгляд (?!$)заботится об этом случае

Спасибо @Zachary за то, что заставил меня понять, что я могу отбросить пробелы (так как это кодовый гольф).
Спасибо @DLosc за улучшения и заставить меня осознать мою ошибку, теперь она исправлена.


2
Некоторое объяснение этому может помочь.
Нисса

x: re.match=> x:re.match; , x=> ,xи ) is=> )isдолжны сохранить 3 байта. Кроме того, в регулярном выражении вы можете использовать \dдля каждого случая [0-9], и [1]=> 1. Это похоже на отличный первый пост, хотя!
Захари

[1-9][0-9]|[0-9]может стать [1-9]\d|\d(согласно совету Захари), который может стать [1-9]?\d. Кроме того, вместо тестирования re.match(...)is not Noneвы можете сделать это, bool(re.match(...))так как совпадающие объекты являются правдивыми и Noneложными. :)
DLosc

Хм. На самом деле, это терпит неудачу в тестовом примере 1.2.3.4.5(а также 1.2.3.4., которого нет в официальном списке тестовых случаев), потому что он может совпадать с точкой вместо конца строки после четвертого числа.
DLosc


2

Древесный уголь , 45 21 байт

I∧⁼№θ.³¬Φ⪪θ.¬№E²⁵⁶Iλι

Попробуйте онлайн! Ссылка на подробную версию кода. Редактировать: 24 байта сохранены путем переноса ответа Япта @ Шегги. Объяснение:

    θ                   Input string
   №                    Count occurrences of
     .                  Literal `.`
  ⁼                     Equal to
      ³                 Literal 3
 ∧                      Logical And
       ¬                Logical Not
          θ             Input string
         ⪪              Split on
           .            Literal `.`
        Φ               Filter by
            ¬           Logical Not
               ²⁵⁶      Literal 256
              E         Map over implicit range
                   λ    Map value
                  I     Cast to string
             №          Count occurrences of
                    ι   Filter value
I                       Cast to string
                        Implicitly print

Сбой для тестовых случаев с отрицательными целыми числами, такими как 123.-50.0.12или 1.1.1.-80. Все остальное вроде работает нормально. Таким образом, <256проверка должна быть in [0,255]вместо.
Кевин Круйссен

@KevinCruijssen На самом деле код для фильтрации недопустимых символов не работал, потому что я забыл изменить переменную во внутреннем цикле. Должно быть исправлено сейчас.
Нил

2

Сетчатка , 46 44 байта

^
.
^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$

Порт Java-ответа @ OlivierGrégoire , так что не забудьте его поддержать!
-2 байта благодаря @Neil .

Попробуйте онлайн .

Объяснение:

^
.                           # Prepend a dot "." before the (implicit) input
^...$                       # Check if the entire string matches the following regex
                            # exactly, resulting in 1/0 as truthy/falsey:
 (                          #  Open a capture group
  \.                        #   A dot "."
    (25[0-5]                #   Followed by a number in the range [250,255]
    |(2[0-4]|         ) \d) #   or by a number in the range [200,249]
    |(      |1\d|     ) \d) #   or by a number in the range [100,199]
    |(          |[1-9]) \d) #   or by a number in the range [10,99]
    |(                )?\d) #   or by a number in the range [0,9]
 )                          #  Close capture group
  {4}                       #  This capture group should match 4 times after each other

Моя попытка (которую я не опубликовал, потому что вопрос был отложен в то время) была той же длины, но не имела \dоптимизации группы, поэтому вы можете сохранить два байта, потому что вам не нужна Mспецификация для Последняя линия.
Нил

Мне удалось уменьшить Retina до 42 байт, портировав ответ Perl 6, но этот ответ также работает в 0.8.2, чего не делает мой порт.
Нил

2

Желе , 11 байт

⁹ḶṾ€ṗ4j€”.ċ

Монадическая ссылка, принимающая список символов, который дает 1 если это правильный адрес и 0иначе. Строит список всех2564знак равно4294967296 адреса, а затем подсчитывает количество вхождений входа в него.

Вот похоже @ Попробуйте онлайн! который использует16( ) а не256( ), так как метод неэффективен!

Как?

⁹ḶṾ€ṗ4j€”.ċ - Link: list of characters, S
⁹           - literal 256
 Ḷ          - lowered range = [0,1,2,...,254,255]
  Ṿ€        - unevaluate €ach = ['0','1',...,['2','5','4'],['2','5','5']]
    ṗ4      - 4th Cartesian power = ALL 256^4 lists of 4 of them
            -               (e.g.: ['0',['2','5','5'],'9',['1','0']])
        ”.  - literal '.' character
      j€    - join for €ach (e.g. ['0','.','2','5','5','.','9','.','1','0'] = "0.255.9.10")
          ċ - count occurrences of right (S) in left (that big list)

Почему версия с 65 536 IP-адресов занимает 1,8 секунды? о_О
Денис

2

Retina , 42 41 байт

~(K`

255*
["^(("|'|]")\.?\b){4}$"L$`
$.`

Попробуйте онлайн! На основании предыдущей версии ответа @ nwellnhof на Perl 6, но 1 байт был сохранен путем кражи \.?\bуловки из ответа @ Deadcode. Объяснение:

K`

Очистить рабочую зону.

255*

Вставьте 255 символов.

["^(("|'|]")\.?\b){4}$"L$`
$.`

Создайте диапазон 0..255, разделенный |s, с префиксом ^((и суффиксом )\.?\b){4}$, таким образом, создавая регулярное выражение^((0|1|...255)\.?\b){4}$ .

~(

Оцените это на исходном входе.


1

Пип , 25 16 байт

a~=X,256RL4J"\."

Принимает IP-адрес кандидата в качестве аргумента командной строки. Попробуйте онлайн! или проверить все контрольные примеры

объяснение

Решение Regex, по сути порт рекурсивного ответа Stax .

                  a is 1st cmdline arg (implicit)
    ,256          Range(256), i.e. [0 1 2 ... 255]
   X              To regex: creates a regex that matches any item from that list
                  i.e. essentially `(0|1|2|...|255)`
        RL4       Create a list with 4 copies of that regex
           J"\."  Join on this string
 ~=               Regex full-match
a                 against the input

1

JavaScript, 89 байт

(_,r=`(${[...Array(256).keys()].join`|`})`)=>RegExp(`^${(r+'\\.').repeat(3)+r}$`).test(_)

Попробуйте онлайн!

Создайте RegExpгруппы захвата из индексов массива, length 256для которого диапазон 0-255объединен с |последующим повторяющимся .символом ( ^(0|1...|255)\.(0|1...|255)\.(0|1...|255)\.(0|1...|255)$), повторяется несколько 3раз, закрывается соединенным массивом, за которым $следует совпадение конца строки, возврата trueили falseрезультата переданного ввода RegExp.prototype.test().

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.