Ответ 1
Если у вас есть grep, просто вызовите grep напрямую:
grep -Po "(\d{1,3}\.){3}\d{1,3}" foo.txt
Я пытаюсь извлечь все ip-адреса из файла. До сих пор я просто использовал
cat foo.txt | perl -pe 's/.*?((\d{1,3}\.){3}\d{1,3}).*/\1/'
но это также печатает строки, которые не содержат соответствия. Я могу исправить это, перейдя через grep, но похоже, что это не должно быть лишним, и может привести к ошибкам, если регулярные выражения не соответствуют друг другу.
Есть ли более простой способ сделать это?
Если у вас есть grep, просто вызовите grep напрямую:
grep -Po "(\d{1,3}\.){3}\d{1,3}" foo.txt
Попробуйте следующее:
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" }'
У вас уже есть подходящий ответ на использование 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
ruby -0777 -ne 'puts $_.scan(/((?:\d{1,3}\.){3}\d{1,3})/)' file