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ó.

Sas
fuente

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.

AB
fuente
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.

unxnut
fuente
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
Cuonglm
fuente
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
αғsнιη
fuente
$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
don_crissti
fuente
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

~ $
k_vishwanath
fuente
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'
Benamar
fuente