Comment remplacer un mot par une nouvelle ligne


11

J'ai un fichier texte avec les données suivantes et chaque ligne se termine par |END|.

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

J'essaie de remplacer |END|par une \nnouvelle ligne avec sed.

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

Mais cela produit une mauvaise sortie comme ci-dessous:

 T
 |
 s
 o
 m
 e
 ...

Mais ce que je veux c'est ceci:

T|somthing|something
T|something2|something2

J'ai aussi essayé avec tr. Ça n'a pas marché non plus.


Réponses:


15

Utilisez ceci:

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

Ce que vous avez tenté ne fonctionne pas car sed utilise des expressions régulières de base , et votre implémentation sed a un \|opérateur qui signifie «ou» (une extension commune à BRE), donc ce que vous avez écrit remplace (chaîne vide ou ENDou chaîne vide) par une nouvelle ligne.


Besoin de commenter le \ in \ n: sed 's / | END | / \\ n / g
Baazigar

@Baazigar Non, ce qu'AB a écrit est correct (pour Linux au moins, certaines implémentations sed émettraient \n). La question demande comment remplacer |END|par une nouvelle ligne, pas par \n.
Gilles 'SO- arrête d'être méchant'

Les caractères de la nouvelle ligne sont '\ n'. Le \\ n est nécessaire car \ est également un caractère d'échappement, donc si vous ne faites que \ n, vous dites "échapper à ce caractère n". Lorsque vous faites \\ n, vous dites "ne traitez pas cette prochaine \ comme une fuite.".
Baazigar

7

Les éléments suivants ont bien fonctionné pour moi:

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

Notez que je viens de mettre une barre oblique inverse suivie de la touche Entrée.


2
Voilà la syntaxe standard. Utiliser \n as dans la réponse de @ AB ne fonctionnerait pas avec certaines sedimplémentations.
Stéphane Chazelas

@ StéphaneChazelas Quelle implémentation sed supporte-t-elle \|pour l'alternance dans une expression rationnelle mais pas \npour une nouvelle ligne dans un sremplacement?
Gilles 'SO- arrête d'être méchant'

5

Vous pouvez utiliser awk:

$ awk -F'\\|END\\|' '{$1=$1}1' OFS='\n' file
T|somthing|something
T|something2|something2
  • -F'\\|END\\|' définissez le séparateur de champ sur |END|
  • OFS='\n' définir le séparateur de champ de sortie sur la nouvelle ligne
  • $1=$1provoquer la awkreconstruction $0avec OFScomme séparateur de champ
  • 1est une valeur vraie, car awkimprime toute la ligne d'entrée

3

Un autre peut-être commande et en utilisant son RSoption serait:

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

Imprimera ces dossiers (sur la base de awk R ECORD S de eparator) qui ne sont pas vides (a au moins un champ) pour empêcher l' impression des lignes vides.

Testé sur cette entrée:

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

Donne cette sortie:

T|somthing|something
T|something2|something2
Test

Cela a effacé toutes les lignes vides :) Si vous voulez aussi avoir des sauts de ligne, remplacez $1=$1par $0dans la commande:

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

$1=$1condense les séquences de blancs en un seul espace et renvoie faux si le premier champ est 0. Cela n'a pas de sens. Vous voulez probablement awk 1 RS='\\|END\\|'ou awk NF RS='\\|END\\|'ou awk length RS='\\|END\\|'ici. Notez qu'une regexp RS nécessite du gawk ou du mawk
Stéphane Chazelas

3

Une autre façon avec sedcela n'imprime pas les lignes vides:

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

par exemple entrée:

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

production:

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

même chose avec ed:

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

1

Comme mentionné ici par Walter Mundt , nous pouvons y parvenir en utilisant une chaîne entre guillemets 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

~ $

Consultez le lien ci-dessus ici pour d'autres alternatives.

Vous pouvez également utiliser la syntaxe suivante, je ne sais pas si cela fonctionne sur toutes les versions d'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

~ $

Travailler sur FreeBSD v10. En fait, seule méthode qui a fonctionné pour moi. Merci.
Sopalajo de Arrierez

0

J'ai eu un même problème dans le shell posix strict, je l'ai fait en deux passes avec un caractère inutilisé

cat data.json|tr '§' '?'|sed -e 's/"[^"]":/§&/g'|tr '§' '\n'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.