Tengo un archivo que contiene los siguientes datos:
GS*PO*112233*445566*20211006*155007*2010408*X*004010~ ST*850*0001~ BEG*00*DS*A-112233**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*SO168219~ REF*DC*ABC~ ST*850*0002~ BEG*00*DS*A-44556**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*PO54361~ ST*850*0003~ BEG*00*DS*A-12345**20211005~ REF*K6*Drop Ship Order~ REF*DC*XYZ~ REF*ZZ*SO897654~ Para mayor claridad, he insertado una línea en blanco encima de cada línea ST*850 . Esto es lo que quiero hacer:
REF*ZZ*SOST*850 con ST*850CAsí que el archivo resultante se vería así:
GS*PO*112233*445566*20211006*155007*2010408*X*004010~ ST*850C*0001~ BEG*00*DS*A-112233**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*SO168219~ REF*DC*ABC~ ST*850*0002~ BEG*00*DS*A-44556**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*PO54361~ ST*850C*0003~ BEG*00*DS*A-12345**20211005~ REF*K6*Drop Ship Order~ REF*DC*XYZ~ REF*ZZ*SO897654~Esto es lo que he probado:
sed -i -n '/^REF\*ZZ\*SO/!{x;s/ST\*850\*/ST\*850C\*/;x};x;1!p;${x;p}' file Esto reemplaza las tres líneas ST*850 con ST*850C y no solo la primera y la tercera. ¿Qué estoy haciendo mal?
Esto podría funcionar para usted (GNU sed):
sed '/ST\*850/{:a;/REF\*ZZ\*SO/!{N;ba};s/.*ST\*850/&C/}' file Comience a recopilar líneas si una línea contiene ST*850 .
Al hacer coincidir una línea que contiene REF*ZZ*SO use greed para agregar C a la última cadena ST*850 .
NB La expresión regular .* asegura que la coincidencia retrocederá desde el final de la colección en lugar del inicio de la colección.
¿Qué tal una solución perl aunque perl no está incluido en las etiquetas?
perl -0777 -aF'(?=ST\*850)' -ne ' print map {/REF\*ZZ\*SO/ && s/ST\*850/$&C/; $_} @F; ' fileProducción:
GS*PO*112233*445566*20211006*155007*2010408*X*004010~ ST*850C*0001~ BEG*00*DS*A-112233**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*SO168219~ REF*DC*ABC~ ST*850*0002~ BEG*00*DS*A-44556**20211005~ REF*K6*Drop Ship Order~ REF*ZZ*PO54361~ ST*850C*0003~ BEG*00*DS*A-12345**20211005~ REF*K6*Drop Ship Order~ REF*DC*XYZ~ REF*ZZ*SO897654~-0777 le dice a perl que sorba todo el archivo a la vez.-a habilita el modo de auto split , luego los fragmentos divididos se almacenan en la matriz @F .-F especifica el patrón para dividir la entrada.(?=ST\*850) es una búsqueda positiva que coincide con el comienzo de una cadena ST*850 .-ne es mayormente equivalente a la de sed .map {..} @F convierte todos los elementos de @F de acuerdo con la declaración entre llaves./REF\*ZZ\*SO/ && s/ST\*850/$&C/ se traduce como: "si el elemento de @F coincide con el patrón /REF*ZZ*SO/, entonces realice la sustitución s/ ST*850/$&C/ para el elemento".$_ final es la variable predeterminada de perl similar al pattern space de sed y serán los valores de retorno de la función de mapa.Suponiendo que ST es esencialmente un separador de registros, puede usar un script Awk simple para recopilar las líneas en el registro actual e imprimir uno diferente modificado si las condiciones son adecuadas.
awk 'BEGIN { ORS = RS = "\nST" } /REF\*ZZ\*SO/ { sub(/^\*850/, "*<850C") }1' filename La cláusula BEGIN establece el separador de registros ( RS ) y también el separador de registros de salida ( ORS ) en la cadena ST precedida por una nueva línea. (Intentar incluir el asterisco se complicó, así que lo evité). El 1 final es la abreviatura común de Awk para "imprimir todo lo que llega aquí".
sed es bastante difícil de manejar para cualquier cosa más allá de simples sustituciones basadas en líneas; Creo que encontrará que cambiar a un lenguaje de nivel superior mejorará la capacidad de mantenimiento.