Perl: получение n-го и m-го слов с разделителями из каждой строки в файле - PullRequest
7 голосов
/ 01 октября 2008

Из-за более утомительного способа добавления хостов, которые нужно отслеживать в Nagios (для этого требуется определить объект хоста, в отличие от предыдущей программы, для которой требовались только IP и имя хоста), я решил, что лучше всего автоматизировать и это было бы отличное время для изучения Perl, потому что все, что я знаю на данный момент, это C / C ++ и Java.

Файл, из которого я читаю, выглядит следующим образом:

xxx.xxx.xxx.xxx hostname #comments. i.dont. care. about

Все, что я хочу, это первые 2 группы персонажей. Они, очевидно, разделены пробелами, но ради общности это может быть что угодно. Чтобы сделать его более общим, почему не первый и третий или четвертый и десятый? Конечно, должно быть какое-то действие с регулярным выражением, но я пока оставлю этот тег на всякий случай.

Ответы [ 7 ]

8 голосов
/ 01 октября 2008

Однострочник хорош, если вы не пишете больше Perl для обработки результата.

В более широком смысле, в контексте более крупной программы на Perl, вы могли бы написать пользовательское регулярное выражение, например:

if($line =~ m/(\S+)\s+(\S+)/) {
     $ip = $1;
     $hostname = $2;
}

... или вы использовали бы оператор split .

my @arr = split(/ /, $line);
$ip = $arr[0];
$hostname = $arr[1];

В любом случае, добавьте логику для проверки правильности ввода.

7 голосов
/ 01 октября 2008

Вот общее решение (если мы немного отойдем от игры в гольф).

#!/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];

Конечно, если вы анализируете файлы, разделенные двоеточиями, также велики шансы, что у таких файлов нет комментариев, и вам не нужно их удалять.

7 голосов
/ 01 октября 2008

Давайте превратим это в код гольф! Исходя из превосходного ответа Дэвида, вот мой:

perl -ane 'print "@F[0,1]\n";'

Редактировать: реальная подача в гольф выглядела бы больше так (сбрить пять ударов):

perl -ape '$_="@F[0,1]
"'

но это менее читабельно для целей этого вопроса. : -Р

6 голосов
/ 01 октября 2008

Простой однострочник

perl -nae 'print "$F[0] $F[1]\n";'

Вы можете изменить разделитель с помощью -F

4 голосов
/ 01 октября 2008

Дэвид Неме сказал:

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) manpage.

0 голосов
/ 31 декабря 2013

Для поиска символа от N до Mth в строке № 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

Сохранить как найти label.cmd

Результатом будет ваш диск E Label

Наслаждайтесь

0 голосов
/ 02 октября 2008

Поскольку Рэй спросил, я решил переписать всю свою программу без использования неявности 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. : -Р

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...