Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

274
Views
Linux bash: ¿Cómo reemplazo una cadena en una línea basada en un patrón en otra línea diferente?

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:

  1. Busca el patrón REF*ZZ*SO
  2. Si lo encuentra, reemplace la línea anterior ST*850 con ST*850C

Así 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?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

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.

over 4 years ago · Santiago Trujillo Report

0

¿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; ' file

Producció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~
  • La opción -0777 le dice a perl que sorba todo el archivo a la vez.
  • La opción -a habilita el modo de auto split , luego los fragmentos divididos se almacenan en la matriz @F .
  • La opción -F especifica el patrón para dividir la entrada.
  • La expresión regular (?=ST\*850) es una búsqueda positiva que coincide con el comienzo de una cadena ST*850 .
  • La opción -ne es mayormente equivalente a la de sed .
  • La función map {..} @F convierte todos los elementos de @F de acuerdo con la declaración entre llaves.
  • La declaración /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".
  • El $_ 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.
over 4 years ago · Santiago Trujillo Report

0

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.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!