Usando OPEN STEP 4.2 OS ... Actualmente estoy usando el siguiente sed
comando:
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
Este comando encontrará una instancia en un archivo con la ip de 141.299.99.1 y también incluirá 3 líneas antes, lo cual es bueno, con la excepción de que también me gustaría encontrar todas las instancias de la IP y las 3 líneas anteriores. y no solo el primero.
Respuestas:
Aquí hay un intento de emular
grep -B3
usando una ventana de movimiento de sed, basado en este ejemplo de GNU sed (pero con suerte compatible con POSIX, con reconocimiento a @ StéphaneChazelas):Las dos primeras expresiones preparan un búfer de patrón de varias líneas y le permiten manejar el caso de borde en el que hay menos de 3 líneas de contexto anterior antes de la primera coincidencia. La expresión del medio (coincidencia de expresiones regulares) imprime una línea desde la parte superior de la ventana hasta que el texto de coincidencia deseado se ondula a través del búfer de patrón. El final
$!N;D
desplaza la ventana una línea, excepto cuando llega al final de la entrada.fuente
-e
no es específico de GNU. Para ser POSIX / portátil, lo necesita ya que no puede haber nada después}
(y necesita un;
antes).-e '1h;2,4{H;g;}' -e '1,3d'
? No tengo un sistema que no sea GNU para probar (y al--posix
interruptor sed de GNU no parece importarle).sed
del heredero de herramientas de herencia que es un descendiente de la tradicional Unix sed. La especificación POSIX / Unixsed
está en pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlgrep
hará un mejor trabajo de esto:Los
-B 3
medios para imprimir las tres líneas antes de cada partido. Esto se imprimirá--
entre cada grupo de líneas. Para deshabilitar eso, úsalo--no-group-separator
también.La
-B
opción es compatible con GNUgrep
y la mayoría de las versiones BSD también ( OSX , FreeBSD , OpenBSD , NetBSD ), pero técnicamente no es una opción estándar.fuente
Con
sed
usted puede hacer una ventana deslizante.Eso lo hace. ¡Pero cuidado -
bash
el comportamiento loco de expandirse!
incluso cuando se cita! en la cadena de comandos de su historial de comandos puede hacer que se vuelva un poco loco. Prefije el comando conset +H;
si encuentra que este es el caso. Para luego volver a habilitarlo (pero ¿por qué ???) hazloset -H
después.Eso, por supuesto, solo se aplicaría si estuviera usando
bash
, aunque no creo que lo esté haciendo. Estoy bastante seguro de que está trabajando concsh
- (que resulta ser el shell cuyo comportamiento locobash
emula con la expansión del historial, pero tal vez no en los extremos que el shell c lo llevó) . Así que , probablemente, una\!
debería funcionar. Espero.Todo es código portátil: POSIX describe sus tres operadores de la siguiente manera: (aunque vale la pena señalar que solo he confirmado que esta descripción existía ya en 2001)
Entonces, en la primera línea, agrega una línea adicional al espacio del patrón, para que se vea así:
A continuación, en la primera línea y cada línea a partir de entonces - con excepción de la última - se agrega otra línea al espacio de patrones. Entonces se ve así:
Si su dirección IP se encuentra dentro de usted,
P
diríjase a la primera línea nueva, así que solo la línea 1 aquí. Al final de cada ciclo,D
eliges lo mismo y comienzas de nuevo con lo que queda. Entonces el siguiente ciclo se ve así:...y así. Si su IP se encuentra en cualquiera de esos tres, se imprimirá la más antigua cada vez. Entonces siempre estás solo tres líneas por delante.
Aquí hay un ejemplo rápido. Obtendré un búfer de tres líneas impreso para cada número que termine en cero:
Eso es un poco más complicado que su caso porque tuve que alternar desde la
0\n
nueva línea o el0$
final del espacio del patrón para parecerse más a su problema, pero son sutilmente diferentes ya que esto requiere un ancla, lo que puede ser un poco difícil de hacer ya que el espacio de patrones cambia constantemente.Utilicé los casos impares de 10 y 52 para mostrar que mientras el ancla sea flexible, también lo será la salida. Totalmente portátil, puedo lograr los mismos resultados al contar con el algoritmo y hacer:
Y ampliar la búsqueda al tiempo que restringe mi ventana: de 0 a 9 y 0 y de 3 líneas a dos.
De todos modos, entiendes la idea.
fuente
sed '...' $filename
. Por cierto, dejé los períodos de su propia cadena de búsqueda, pero esos no son realmente períodos en un patrón, representan cualquier carácter individual. Probablemente deberías haceroct\.oct\.oct\.oct
para escapar de ellos para que solo coincidan con los períodos.Como mencionas que no tienes la
-B
opcióngrep
, puedes usar Perl (por ejemplo) para hacer una ventana deslizante de 4 líneas:La respuesta de Ramesh hace algo similar con
awk
.fuente
Cuando esté disponible, puede usar pcregrep :
fuente
Puede implementar el mismo enfoque básico que las otras respuestas no grep en el propio shell (esto supone un shell relativamente reciente que admite
=~
):Alternativamente, puede sorber todo el archivo en una matriz:
fuente
Si su sistema no es compatible con el
grep
contexto, puede probar ack-grep en su lugar:ack
es una herramienta como grep, optimizada para programadores.fuente
perl
, puedes usarack
.En esta
awk
solución, se usa una matriz que siempre contendrá 3 líneas antes del patrón actual. Por lo tanto, cuando el patrón coincide, se imprime el contenido de la matriz junto con el patrón actual.Pruebas
Después de ejecutar el comando, la salida es,
fuente
En la mayoría de estos,
/141.299.99.1/
también coincidirá (por ejemplo)141a299q99+1
o141029969951
porque.
en una expresión regular puede representar cualquier carácter.El uso
/141[.]299[.]99[.]1/
es más seguro, y se puede añadir un contexto adicional al principio y al final de toda la expresión regular para asegurarse de que no coincide3141.
,.12
,.104
, etc.fuente