Busque un conjunto de líneas desde $START hasta $END Y que contenga una coincidencia en $MIDDLE

Busque un conjunto de líneas desde $START hasta $END Y que contenga una coincidencia en $MIDDLE

Grep/Awk/Sed para un conjunto de líneas de "0010|" a "0070|" Y que contiene una coincidencia en el $PH_NO

A continuación se muestran los datos de muestra. Necesito buscar el número de teléfono que se presenta en el campo 0012 y los registros completos de clientes correspondientes, líneas del 0010 al 0070. Un archivo de datos puede contener dos o tres registros de clientes con el mismo número de teléfono y necesito obtenerlos todos.

0010|Kumar||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|RAM||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 333| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|
0010|Joe||57 Rich street|Chennai|Tamil Nadu|
0011|20171115| ID
0012|149 196 222| PH Number 
0013|20161101|20171102|
0022|Payment Method |Lucky customer|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|P|5.00-|20161111|Payment|
0080|P|5.00-|20161130|Payment|
0080|TP|10.00-|||
0070|000AYDCHDFF|820|762|

Nota: estoy en un servidor AIX con ksh.

Respuesta1

Entonces, ¿quiere el registro completo de 0010 a 0070, si el número de PH coincide $PH_NO"? Entonces este sedoneliner funcionará:

sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
  • /^0010/,/^0070/Hpara agregar un registro del 0010 al 0070 al espacio de retención
  • /^0010/hel 0010 no debería agregarse, pero debe comenzar un nuevo registro, así que cópielo en el espacio de espera
  • /^0070/! dno hay más procesamiento o salida a menos que sea el artículo 0070
  • x;/|$PH_NO| PH Number/! d"intercambie los espacios, de modo que todo el registro esté ahora en el espacio del patrón y elimínelo si no contiene dicho número.

Respuesta2

for r in `grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed 's/,[0-9]\+,/,/g'`; do sed -n "$r"p CUSTOMER_FILE; echo; done

149 196 222en el comando anterior está el número de teléfono del cliente. Cámbielo por el número de teléfono que desea averiguar.

CUSTOMER_FILEes el archivo que desea buscar. Cámbielo por el nombre de su archivo.

También puede colocar el código en un script bash y reemplazarlo 149 196 222con $1y reemplazarlo CUSTOMER_FILEcon $2. Di find-customer.sh, luego puedes ejecutar el script como este

./find-customer.sh '149 196 222' your-file-name

Requisito previo de este fragmento de código:

  1. Bash, entorno GNU (GNU grep, GNU sed)
  2. Su archivo debe seguir el formato como se muestra a continuación. 0010 ... <no 0010 or 0012 or 0070> ... 0012 ... <no 0010 or 0012 or 0070> ... 0070 ... <repeated content as above or end of file>


ACTUALIZAR

Esta es una versión de alto rendimiento. (Al menos más alto que el original anterior. No hay ningún bucle for involucrado).

grep -n '^0010\|^0012\|^0070' CUSTOMER_FILE | grep -C1 '[0-9]\+:0012|149 196 222|' | grep -o '^[0-9]\+' | paste -d, - - - | sed -r 's|([0-9]+),[0-9]+,([0-9]+)|\1,\2p;\2a|g' | sed -n -f - CUSTOMER_FILE


ACTUALIZACIÓN para AIX

Dado que el autor de la pregunta está trabajando en AIX. El grep en AIX no admite opciones de contexto, -A, -B, -C.

En Internet, hay una variedad de implementaciones "cgrep" (context grep) para resolver este problema (para simular la opción de contexto grep de GNU). Pero la mayoría de ellos no pueden dar el mismo resultado que GNU grep. Sólo uno que encontré es el más cercano a la opción de contexto grep de GNU. El enlace eshttps://stackoverflow.com/questions/1685678/advanced-grep-unix/1685782#1685782

Hice algunas modificaciones necesarias para este caso.

#!/bin/bash
BEFORE=$1
AFTER=$1
FILE=/tmp/.cattmp
PATTERN="$2"
cat > $FILE
for i in $(grep -n "$PATTERN" $FILE | sed -e 's/\:.*//')
  do head -n $(($AFTER+$i)) $FILE | tail -n $(($AFTER+$BEFORE+1))
done
rm $FILE

Guarde este archivo como grep-context.shy reemplácelo grep -C1con ./grep-context.sh 1mi comando anterior.

Otra forma que creo que es de una vez por todas es compilar GNU grep en AIX. (también compila GNU sed por si acaso)

Respuesta3

Puedes usar este script:

#!/bin/sh
read START
read END
read MATCH

REND=$(grep -n "$END" lines | tail -1 | cut -d":" -f 1)
RSTART=$(grep -n "$START" lines | head -1 | cut -d":" -f 1)

sed $RSTART,$REND!d lines | grep "$MATCH"

Ponlo en un archivo y agrega el permiso de ejecución con este comando.

chmod +x script.sh

variable de INICIO:Su número de línea inicial (por ejemplo, 0010)

Variable FINAL:Su variable final (por ejemplo, 0070)

Variable COINCIDIR:La palabra/carácter/número que busca en una línea (por ejemplo, 0012)

Variable RINICIO:El número de línea inicial en el archivo de texto (por ejemplo, 1)

RENDIR variable:El número de línea inicial en el archivo de texto (por ejemplo, 32)


EDITAR:

También puedes ver cuántas veces se repite una línea, cambiando la última línea a esto:

sed $RSTART,$REND!d lines | grep "$MATCH" | sort | uniq -c

información relacionada