Perl:Захват n-го и m-го слов с разделителями из каждой строки файла

StackOverflow https://stackoverflow.com/questions/156009

  •  03-07-2019
  •  | 
  •  

Вопрос

Из-за более утомительного способа добавления отслеживаемых хостов в 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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top