Perl: pegando as enx e mth delimitadas palavras de cada linha em um arquivo
Pergunta
Devido à maneira mais tediosa de adicionar hosts a serem monitorados em Nagios (requer definir um objeto host, em oposição ao programa anterior que só exigia o IP e o nome do host), imaginei que seria melhor automatizar isso e ele É um ótimo momento para aprender Perl, porque tudo o que sei no momento é C/C ++ e Java.
O arquivo que eu li parece o seguinte:
xxx.xxx.xxx.xxx hostname #comments. i.dont. care. about
Tudo que eu quero são os 2 primeiros cachos de personagens. Obviamente, são delimitados espaciais, mas, por uma questão de generalidade, pode muito bem ser qualquer coisa. Para torná -lo mais geral, por que não o primeiro e o terceiro, ou quarto e décimo? Certamente deve haver alguma ação regex envolvida, mas deixarei essa etiqueta por um momento, apenas por precaução.
Solução
A linha é ótima, se você não está escrevendo mais Perl para lidar com o resultado.
De maneira mais geral, no entanto, no contexto de um programa PERL maior, você escreveria uma expressão regular personalizada, por exemplo:
if($line =~ m/(\S+)\s+(\S+)/) {
$ip = $1;
$hostname = $2;
}
... ou você usaria o dividir operador.
my @arr = split(/ /, $line);
$ip = $arr[0];
$hostname = $arr[1];
De qualquer maneira, adicione a lógica para verificar a entrada inválida.
Outras dicas
Vamos transformar isso em Code Golf! Com base na excelente resposta de David, aqui está minha:
perl -ane 'print "@F[0,1]\n";'
Editar: Uma verdadeira submissão de golfe seria mais com isso (raspar cinco golpes):
perl -ape '$_="@F[0,1]
"'
Mas isso é menos legível para os propósitos desta pergunta. :-P
Aqui está uma solução geral (se nos afastarmos do jogo de código um pouco).
#!/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";
Normalmente split
dividido por espaço em branco. Se não é isso que você quer (por exemplo, analisar /etc/passwd
), você pode passar por um delimitador como regex:
@fields = (split /:/)[0,2,4..6];
Obviamente, se você está analisando arquivos delimitados por cólon, é bom que esses arquivos não tenham comentários e você não precise retirá-los.
Uma simples liner é
perl -nae 'print "$F[0] $F[1]\n";'
você pode mudar o delimitador com -F
David Nehme disse:
perl -nae 'print "$F[0] $F[1}\n";
que usa o -a
trocar. Eu tive que procurar aquele:
-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.
Você aprende algo todo dia. -n faz com que cada linha seja passada para
LINE:
while (<>) {
... # your program goes here
}
E finalmente -e
é uma maneira de inserir diretamente uma única linha de um programa. Você pode ter mais do que -e
. A maior parte disso foi um rasgo do perlrun(1)
MANPAGE.
Desde que Ray perguntou, pensei em reescrever todo o meu programa sem usar a implícita de Perl (exceto o uso de <ARGV>
; Isso é difícil de escrever à mão). Isso provavelmente tornará as pessoas do Python mais felizes (apesar do aparelho: P):
while (my $line = <ARGV>) {
chop $line;
$line =~ s/#.*//;
next unless $line =~ /\S/;
@fields = (split ' ', $line)[0,1];
print join(' ', @fields), "\n";
}
Há algo que eu perdi? Espero que não. o ARGV
FileHandle é especial. Isso faz com que cada arquivo nomeado na linha de comando seja lido, a menos que nenhum seja especificado; nesse caso, lê a entrada padrão.
EDIT: Oh, eu esqueci. split ' '
também é mágico, diferentemente split / /
. Este último combina um espaço. O primeiro corresponde a qualquer quantidade de espaço em branco. Este comportamento mágico é usado por padrão se nenhum padrão for especificado para split
. (Alguns diriam, Mas que tal /\s+/
? ' '
e /\s+/
são semelhantes, exceto como o espaço em branco no início de uma linha é tratado. Então ' '
realmente é mágico.)
A moral da história é: Perl é ótimo se você gosta de muito comportamento mágico. Se você não tiver uma barra, use Python. :-P
Para encontrar o Nth a Mth Caracter na linha No. L --- Exemplo para encontrar o rótulo
@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
Salvar como encontre gravador.cmd
O resultado será o seu rótulo de unidade e
Apreciar