Только распечатать соответствующие строки в perl из командной строки

Я пытаюсь извлечь все ip-адреса из файла. До сих пор я просто использовал

cat foo.txt | perl -pe 's/.*?((\d{1,3}\.){3}\d{1,3}).*/\1/'

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

Есть ли более простой способ сделать это?

Ответ 1

Если у вас есть grep, просто вызовите grep напрямую:

grep -Po "(\d{1,3}\.){3}\d{1,3}" foo.txt

Ответ 2

Попробуйте следующее:

cat foo.txt | perl -ne 'print if s/.*?((\d{1,3}\.){3}\d{1,3}).*/\1/'

или

<foo.txt perl -ne 'print if s/.*?((\d{1,3}\.){3}\d{1,3}).*/\1/'

Это самая короткая альтернатива, которую я могу придумать при использовании Perl.

Однако этот способ может быть более правильным:

<foo.txt perl -ne 'if (/((\d{1,3}\.){3}\d{1,3})/) { print $1 . "\n" }'

Ответ 3

У вас уже есть подходящий ответ на использование grep для извлечения IP-адресов, но просто для объяснения того, почему вы печатали не-матчи:

perldoc perlrun расскажет вам обо всех параметрах, которые вы можете передать Perl в командной строке.

Цитата из этого:

-p   causes Perl to assume the following loop around your program, which makes it 
     iterate over filename arguments somewhat like sed:

     LINE:
     while (<>) {
         ...             # your program goes here
     } continue {
         print or die "-p destination: $!\n";
     }

Вместо этого вы могли бы использовать вместо этого переключатель -n, который аналогичен, но не печатает автоматически, например:

cat foo.txt | perl -ne '/((?:\d{1,3}\.){3}\d{1,3})/ and print $1'

Кроме того, нет необходимости использовать cat; Perl откроет и прочитает имена файлов, которые вы ему даете, поэтому вы можете сказать, например:

perl -ne '/((?:\d{1,3}\.){3}\d{1,3})/ and print $1' foo.txt

Ответ 4

ruby -0777 -ne 'puts $_.scan(/((?:\d{1,3}\.){3}\d{1,3})/)' file