Perla:Tomando las palabras delimitadas enésima y enésima de cada línea en un archivo

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Debido a la forma más tediosa de agregar hosts para monitorear en Nagios (requiere definir un objeto de host, a diferencia del programa anterior que solo requería la IP y el nombre de host), pensé que sería mejor automatizar esto, y Sería un buen momento para aprender Perl, porque todo lo que sé en este momento es C/C++ y Java.

El archivo que leí se ve así:

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

Todo lo que quiero son los primeros 2 grupos de personajes.Obviamente, estos están delimitados por espacio, pero en aras de la generalidad, bien podría ser cualquier cosa.Para hacerlo más general, ¿por qué no el primero y el tercero, o el cuarto y el décimo?Seguramente debe haber alguna acción de expresión regular involucrada, pero dejaré esa etiqueta desactivada por el momento, por si acaso.

¿Fue útil?

Solución

El one-liner es genial, si no estás escribiendo más Perl para manejar el resultado.

Más generalmente, sin embargo, en el contexto de un programa Perl más grande, escribiría una expresión regular personalizada, por ejemplo:

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

... o usaría el operador split .

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

De cualquier manera, agregue lógica para verificar la entrada no válida.

Otros consejos

¡Convirtamos esto en golf de código! Basado en la excelente respuesta de David, aquí está la mía:

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

Editar: una presentación de golf real se vería más así (quitando cinco golpes):

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

pero eso es menos legible para los propósitos de esta pregunta. :-P

Aquí hay una solución general (si nos alejamos un poco del golf de código un poco).

#!/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 se divide por espacios en blanco. Si eso no es lo que desea (por ejemplo, análisis /etc/passwd), puede pasar un delimitador como una expresión regular:

@fields = (split /:/)[0,2,4..6];

Por supuesto, si está analizando archivos delimitados por dos puntos, también es probable que dichos archivos no tengan comentarios y no tenga que quitarlos.

Una línea simple es

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

puede cambiar el delimitador con -F

David Nehme dijo:

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

que usa el interruptor -a. Tuve que buscarlo:

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

aprendes algo todos los días. -n hace que cada línea se pase a

LINE:
    while (<>) {
        ...             # your program goes here
    }

Y finalmente -e es una forma de ingresar directamente una sola línea de un programa. Puedes tener más de perlrun(1). La mayor parte de esto fue una copia de la <=> página de manual.

Como Ray preguntó, pensé en reescribir todo mi programa sin usar la implícitaidad de Perl (excepto el uso de <ARGV>;eso es difícil de escribir a mano).Esto probablemente hará que la gente de Python sea más feliz (a pesar de las llaves :-P):

while (my $line = <ARGV>) {
    chop $line;
    $line =~ s/#.*//;
    next unless $line =~ /\S/;
    @fields = (split ' ', $line)[0,1];
    print join(' ', @fields), "\n";
}

¿Hay algo que me perdí?Ojalá no.El ARGV El identificador de archivo es especial.Hace que se lea cada archivo nombrado en la línea de comando, a menos que no se especifique ninguno, en cuyo caso lee la entrada estándar.

Editar:Oh, lo olvidé. split ' ' También es mágico, a diferencia split / /.Este último sólo coincide con un espacio.El primero coincide con cualquier cantidad de espacio en blanco.Este comportamiento mágico se utiliza de forma predeterminada si no se especifica ningún patrón para split.(Algunos dirían, pero que pasa /\s+/? ' ' y /\s+/ son similares, excepto por cómo se tratan los espacios en blanco al principio de una línea.Entonces ' ' realmente es mágico.)

La moraleja de la historia es que Perl es genial si te gustan muchos comportamientos mágicos.Si no tienes una barra, usa Python.:-PAG

Para buscar caracteres Nth a Mth en la línea No. L --- Ejemplo para encontrar la etiqueta


@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

Guardar como find label.cmd

El resultado será su etiqueta de unidad E

Disfruta

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top