![Busque un conjunto de líneas desde $START hasta $END Y que contenga una coincidencia en $MIDDLE](https://rvso.com/image/122435/Busque%20un%20conjunto%20de%20l%C3%ADneas%20desde%20%24START%20hasta%20%24END%20Y%20que%20contenga%20una%20coincidencia%20en%20%24MIDDLE.png)
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 sed
oneliner funcionará:
sed "/^0010/,/^0070/H;/^0010/h;/^0070/! d;x;/|$PH_NO| PH Number/! d"
/^0010/,/^0070/H
para agregar un registro del 0010 al 0070 al espacio de retención/^0010/h
el 0010 no debería agregarse, pero debe comenzar un nuevo registro, así que cópielo en el espacio de espera/^0070/! d
no hay más procesamiento o salida a menos que sea el artículo 0070x;/|$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 222
en 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_FILE
es 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 222
con $1
y reemplazarlo CUSTOMER_FILE
con $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:
- Bash, entorno GNU (GNU grep, GNU sed)
- 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.sh
y reemplácelo grep -C1
con ./grep-context.sh 1
mi 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