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, -и т. Д. :) Это 1šдля тестового примера 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.