Estamos analizando algunos archivos EDI grandes que no contienen CR / LF. Sin embargo, tienen ~
( tilde ) como un delimitador de segmento.
Estoy tratando de extraer el registro de control para el archivo y los últimos bytes de mi archivo de 120 MB se parecen a esto:
~REF*1L*0711882~SE*62300*39093~GE*1*500001242~IEA*1*500001241~
Solo hay un registro de control en el archivo y siempre comienza con ~SE
.
Entonces, ¿hay una manera fácil de usar Unix estándar cortar , awk , grep , etc. herramientas para cortar este archivo para obtener el segmento SE * 62300 * 39093, aparte de convertir el ~
a CRLF y siguiendo las últimas tres líneas del archivo?
Renuncia:
No soy un gurú de Unix, por lo que la respuesta puede ser obvia para un usuario experimentado. Además, no tengo control sobre el formato de archivo.
~
a nuevas líneas y siguiendo las últimas 3 líneas del archivo. Si se sabe que el archivo no contiene nuevas líneas, esto no introduce ninguna ambigüedad en el formato y, francamente, es la mejor forma de incluir el archivo en un formato que facilite el trabajo de todas las herramientas basadas en líneas.tail
. No hay necesidad de analizarlo todo. Algo comotail edi_file | grep ~SE | cut -d'~' -f 3
(donde edi_file es el nombre de su archivo grande) (Descargo de responsabilidad: el ejemplo solo funciona si el campo requerido está en el campo # 3 (delimitado por ~ 's como por -d~
. Eso podría necesitar un ajuste. ¿Podemos obtener un ejemplo más grande del archivo de entrada?tail --bytes=5000 ding
... y luego esperas que los últimos 5000 bytes sean suficientes para abarcar las 3 líneas que necesitas.Respuestas:
Puedes hacer esto con:
tr "~" "\n" < edi_file | tail -20 | grep ^SE
El tr tr Anuncia todos los tildes a nuevas líneas. (Los que están representados por un \ n).
La salida que luego envió a la cola, que descarta todas, excepto las últimas 20 líneas.
Probablemente pueda ajustar esto, dependiendo de lo que quiera buscar. Sin él, todo el archivo se alimenta a grep, que probablemente requiere muchos más recursos que la cola. Si tiene una versión específica de tail que admite mostrar parte de un archivo basado en bytes en lugar de líneas, incluso puede utilizar este paso antes.
No elegí esa opción porque tu publicación está etiquetada como genérica Unix más bien que Linux moderno con herramientas GNU actualizadas y extensiones específicas de GNU .
Finalmente
grep
Filtra las líneas finales a las que contienen SE, y la carretilla (^
) se asegura de que esté al principio en una línea. (Previniendo cosas como ~ foooo SE foobarquz ~ SE Queremos mostrar ~ boobar ~ para mostrar dos líneas).fuente
Si bien puedo ver que no quiero modificar el archivo original, puedes hacer la traducción en una canalización. De esa manera, no está modificando los datos, pero aún así obtiene la ventaja (en términos de utilidad de Unix) de convertir
~
en fin de línea.Esto debería funcionar:
No es la cosa más eficiente del universo, pero incluso en un archivo de 120 MB no debería ser un gran problema para ejecutar.
Tenga en cuenta que las citas en los dos conjuntos no son opcionales, ambos
~
y\n
será interpretado por el shell si sueltas las comillas.fuente
tr "~" "\n" < edi_file | tail -20 | grep ^SE
? (No hay necesidad de usarcat
cuando la entrada puede ser redirigida Grep para mostrar solo los campos que comienzan con SE.Será ineficiente en archivos grandes
tr
Primero, porque realmente quieres datos del final, ytr
Procesará los datos que serán descartados.Utilizar
tac
para leer el archivo a la inversa, luego tome las 20 primeras líneas (de la inversa, así que en realidad la última), invierta nuevamente para obtener el pedido original, ahoragrep
:Recuerda que no puedes
seek()
¡un tubo!fuente
tac
se convertirá en nuevas líneas, por lo quetr
no debería ser necesario-s
bandera paratac