2008-10-01 1 views
5

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

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

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

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

ответ

6

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

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

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

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

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

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

5

Простой один-лайнер

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

вы можете изменить разделитель с -F

7

Давайте превратить это в код игры в гольф! На основании отличного ответа Давида, вот мой:

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

Edit: Реальное представление гольф будет выглядеть следующим образом (бреет пять ударов):

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

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

+0

Хорошо играл, сэр. – Axeman 2008-10-01 02:52:14

+0

Спасибо! Я внес изменения в запись с чем-то даже в гольф, но, вероятно, еще более неразборчивым. :-P – 2008-10-01 03:00:28

3

Дэвид Nehme сказал:

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

+0

Режим «автосплит» также известен как «awk mode», а использование @F в качестве имени массива берется из awk. – rjray 2008-10-01 02:53:18

6

Вот общее решение (если мы немного отступим от кода-гольфа).

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

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

+0

Вы должны почти всегда использовать chomp вместо измельчения. chop всегда удаляет последний символ из строки. chomp удаляет текущий строковый ограничитель (обычно «\ n») из строки, если он присутствует. Если линия не заканчивается терминатором, chomp ничего не делает. измельчение может удалить вещи, которые вы не ожидаете. – cjm 2008-10-01 05:16:19

+0

Путь Unix состоит в том, что все текстовые файлы заканчиваются новой строкой. Таким образом, вы никогда не читаете строку без новой строки в конце, если ваш файл не заполнен. Это удваивается для файлов, подобных файлам/etc. :-) – 2008-10-01 06:06:32

0

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

0

найти NTH для Mth символов в позиции № L --- например, для отыскания Label


@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 Ярлык

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

Смежные вопросы