Cómo reemplazar una palabra con una nueva línea


11

Tengo un archivo de texto con los siguientes datos y cada fila termina con |END|.

T|somthing|something|END|T|something2|something2|END|

Estoy tratando de reemplazar |END|con una \nnueva línea con sed.

 sed 's/\|END\|/\n/g' test.txt

Pero está produciendo resultados incorrectos como a continuación:

 T
 |
 s
 o
 m
 e
 ...

Pero lo que quiero es esto:

T|somthing|something
T|something2|something2

También lo intenté con tr. Tampoco funcionó.


Respuestas:


15

Utilizar este:

sed 's/|END|/\n/g' test.txt

Lo que intentó no funciona porque sed usa expresiones regulares básicas , y su implementación sed tiene un \|operador que significa "o" (una extensión común a BRE), por lo que lo que escribió reemplaza (cadena ENDvacía o cadena vacía) por una nueva línea.


Necesito comentar el \ in \ n: sed 's / | END | / \\ n / g
Baazigar

@Baazigar No, lo que AB escribió es correcto (al menos para Linux, algunas implementaciones sed emitirían \n). La pregunta pregunta cómo reemplazar |END|por una nueva línea, no por \n.
Gilles 'SO- deja de ser malvado'

Los caracteres para la nueva línea son '\ n'. El \\ n es necesario porque \ también es un carácter de escape, por lo que si solo hace \ n, está diciendo 'escapar de este n carácter'. Cuando lo haces, estás diciendo 'no trates esto a continuación como un escape'.
Baazigar

7

Lo siguiente funcionó bien para mí:

$ sed 's/|END|/\
/g' foobar
T|somthing|something
T|something2|something2

Tenga en cuenta que acabo de poner una barra invertida seguida de la tecla Intro.


2
Esa es la sintaxis estándar. Usar \n como en la respuesta de @ AB no funcionaría con algunas sedimplementaciones.
Stéphane Chazelas

@ StéphaneChazelas ¿Qué implementación sed admite \|para la alternancia en una expresión regular pero no \nsignifica nueva línea en un sreemplazo?
Gilles 'SO- deja de ser malvado'

5

Puedes usar awk:

$ awk -F'\\|END\\|' '{$1=$1}1' OFS='\n' file
T|somthing|something
T|something2|something2
  • -F'\\|END\\|' establecer separador de campo en |END|
  • OFS='\n' establecer el separador de campo de salida en nueva línea
  • $1=$1causa awkreconstruir $0con OFScomo separador de campo
  • 1es un valor verdadero, porque awkimprime toda la línea de entrada

3

Otro posiblemente comando y usar su RSopción sería:

awk '$1=$1' RS="\|END\|" file

Imprimirá esos registros (basado en awk de R ECORD S eparator) que no están vacías (tiene al menos un campo) para evitar la impresión de líneas vacías.

Probado en esta entrada:

T|somthing|something|END|T|something2|something2|END|
Test|END|
|END|

Da este resultado:

T|somthing|something
T|something2|something2
Test

Eso borró todas las líneas vacías :) Si desea tener nuevas líneas también, reemplace $1=$1con el $0comando:

awk '$0' RS="\|END\|" file

$1=$1condensa secuencias de espacios en blanco en un carácter de espacio y devuelve falso si el primer campo es 0. No tiene sentido. Es posible que desee awk 1 RS='\\|END\\|'o awk NF RS='\\|END\\|'o awk length RS='\\|END\\|'aquí. Tenga en cuenta que una expresión regular RS requiere gawk o mawk
Stéphane Chazelas

3

Otra forma con sedeso no imprime líneas vacías:

sed 's/|END|/\
/g;/^$/!P;D' infile

por ejemplo, entrada:

T|one|two|END|T|three|four|END|
T|five|six|END|T|seven|eight|END|
T|nine|ten|END|T|eleven|twelve|END|

salida:

T|one|two
T|three|four
T|five|six
T|seven|eight
T|nine|ten
T|eleven|twelve

Lo mismo con ed:

ed -s infile <<'IN'
1,$j
s/|END|/\
/g
,p
q
IN

1

Como se menciona aquí por Walter Mundt , podemos lograr esto usando una cadena citada ANSI C

sed $'s/|END|/\\\n/g'

~ $ echo 'T|somthing|something|END|T|something2|something2|END|' | sed 
$'s/|END|/\\\n/g'
T|somthing|something
T|something2|something2

~ $

Mira el enlace de arriba para otras alternativas.

También puede usar la siguiente sintaxis, no estoy seguro si funciona en todos los sabores de Unix / Linux

sed 's/|END|/\'$'\n''/g'

~ $ echo 'T|somthing|something|END|T|something2|something2|END|' | sed 
's/|END|/\'$'\n''/g'
T|somthing|something
T|something2|something2

~ $

Trabajando en FreeBSD v10. En realidad, el único método que funcionó para mí. Gracias.
Sopalajo de Arrierez

0

Tuve el mismo problema en el estricto shell posix. Lo hice en dos pasadas con un char no utilizado.

cat data.json|tr '§' '?'|sed -e 's/"[^"]":/§&/g'|tr '§' '\n'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.