Perl:Захват n-го и m-го слов с разделителями из каждой строки файла
Вопрос
Из-за более утомительного способа добавления отслеживаемых хостов в Nagios (он требует определения объекта host, в отличие от предыдущей программы, которая требовала только IP и имя хоста), я решил, что лучше всего это автоматизировать, и было бы отличным временем для изучения Perl, потому что все, что я знаю на данный момент, - это C / C ++ и Java.
Файл, который я прочитал, выглядит примерно так:
xxx.xxx.xxx.xxx hostname #comments. i.dont. care. about
Все, что мне нужно, - это первые 2 группы символов.Очевидно, что они разделены пробелами, но для пущей общности это может быть что угодно.Чтобы сделать это более общим, почему бы не первое и третье, или четвертое и десятое?Конечно, должно быть задействовано какое-то действие с регулярным выражением, но я пока оставлю этот тег отключенным, на всякий случай.
Решение
Однострочник - это здорово, если вы не пишете больше на Perl для обработки результата.
Однако в более общем плане, в контексте более крупной программы на Perl, вы могли бы либо написать пользовательское регулярное выражение, например:
if($line =~ m/(\S+)\s+(\S+)/) {
$ip = $1;
$hostname = $2;
}
...или вы бы использовали расколотый оператор.
my @arr = split(/ /, $line);
$ip = $arr[0];
$hostname = $arr[1];
В любом случае, добавьте логику для проверки на наличие недопустимых входных данных.
Другие советы
Давайте превратим это в code golf!Основываясь на превосходном ответе Дэвида, вот мой:
perl -ane 'print "@F[0,1]\n";'
Редактировать:Настоящая подача в гольф выглядела бы примерно так (отбивание пяти ударов).:
perl -ape '$_="@F[0,1]
"'
но это менее читабельно для целей данного вопроса.:-П
Вот общее решение (если мы немного отойдем от игры в гольф с кодом).
#!/usr/bin/perl -n
chop; # strip newline (in case next line doesn't strip it)
s/#.*//; # strip comments
next unless /\S/; # don't process line if it has nothing (left)
@fields = (split)[0,1]; # split line, and get wanted fields
print join(' ', @fields), "\n";
Обычно split
разделяется пробелом.Если это не то, что вы хотите (например, синтаксический анализ /etc/passwd
), вы можете передать разделитель в виде регулярного выражения:
@fields = (split /:/)[0,2,4..6];
Конечно, если вы анализируете файлы, разделенные двоеточием, велика также вероятность того, что такие файлы не содержат комментариев и вам не нужно их удалять.
Простой однострочник - это
perl -nae 'print "$F[0] $F[1]\n";'
вы можете изменить разделитель с помощью -F
David Nehme said:
perl -nae 'print "$F[0] $F[1}\n";
который использует -a
выключатель.Я должен был посмотреть на это:
-a turns on autosplit mode when used with a -n or -p. An implicit split
command to the @F array is done as the first thing inside the implicit
while loop produced by the -n or -p.
каждый день ты чему-то учишься.-n приводит к передаче каждой строки в
LINE:
while (<>) {
... # your program goes here
}
И, наконец, -e
это способ прямого ввода одной строки программы.У вас может быть больше, чем -e
.Большая часть этого была разрывом perlrun(1)
справочная страница.
Поскольку рэй спросил, я подумал, что перепишу всю свою программу без использования имплицитности Perl (за исключением использования <ARGV>
;это трудно написать от руки).Вероятно, это сделает людей, работающих на Python, счастливее (несмотря на фигурные скобки :-P):
while (my $line = <ARGV>) {
chop $line;
$line =~ s/#.*//;
next unless $line =~ /\S/;
@fields = (split ' ', $line)[0,1];
print join(' ', @fields), "\n";
}
Есть ли что-нибудь, что я пропустил?Надеюсь, что нет.Тот Самый ARGV
дескриптор файла - это нечто особенное.Это приводит к считыванию каждого именованного файла в командной строке, если только ни один из них не указан, и в этом случае он считывает стандартный ввод.
Редактировать:О, я совсем забыла. split ' '
тоже волшебный, в отличие от split / /
.Последнее просто соответствует пробелу.Первый соответствует любому количеству любых пробелов.Это магическое поведение используется по умолчанию, если шаблон не указан для split
.(Некоторые сказали бы, но как насчет /\s+/
? ' '
и /\s+/
они похожи, за исключением того, как обрабатываются пробелы в начале строки.Итак ' '
действительно волшебно.)
Мораль этой истории такова: Perl великолепен, если вам нравится много магического поведения.Если у вас его нет, используйте Python.:-П
Чтобы найти От N-го до M-го символа В строке No.L --- Пример поиска метки
@echo off
REM Next line = Set command value to a file OR Just Choose Your File By Skipping The Line
vol E: > %temp%\justtmp.txt
REM Vol E: = Find Volume Lable Of Drive E
REM Next Line to choose line line no. +0 = line no. 1
for /f "usebackq delims=" %%a in (`more +0 %temp%\justtmp.txt`) DO (set findstringline=%%a& goto :nextstep)
:nextstep
REM Next line to read nth to mth Character here 22th Character to 40th Character
set result=%findstringline:~22,40%
echo %result%
pause
exit /b
Сохранить как find label.cmd
Результатом будет ваша Метка Drive E
Наслаждайтесь