trn'est le bon outil pour le travail que si remplacer un seul caractère par un seul caractère, tandis que l'exemple ci-dessus montre remplacer la nouvelle ligne par un espace. Donc dans l'exemple ci-dessus, tr pourrait fonctionner .. Mais serait limitant plus tard.
Angry 84
9
trdans le bon outil pour le travail parce que le questionneur voulait remplacer chaque nouvelle ligne par un espace, comme le montre son exemple. Le remplacement des sauts de ligne est uniquement mystérieux sedmais facile à réaliser tr. C'est une question courante. Effectuer des remplacements de regex ne se fait pas par trmais par sed, ce qui serait le bon outil ... pour une question différente.
Mike S
3
"tr" peut aussi simplement supprimer la nouvelle ligne `tr -d '\ n' 'mais vous pouvez également supprimer les retours pour être plus universel` tr -d' \ 012 \ 015 ''.
anthony
2
AVERTISSEMENT: "tr" agit différemment en ce qui concerne une plage de caractères entre Linux et les anciennes machines Solaris (EG sol5.8). EG: `tr -d 'az' 'et` tr -d' [az] ''. Pour cela, je vous recommande d'utiliser "sed" qui n'a pas cette différence.
anthony
2
@MikeS Merci pour la réponse. Suivez tr '\012' ' 'avec un echo. Sinon, le dernier saut de ligne du fichier est également supprimé. tr '\012' ' ' < filename; echofait l'affaire.
Bernie Reiter
Réponses:
1514
Utilisez cette solution avec GNU sed:
sed ':a;N;$!ba;s/\n/ /g' file
Cela lira le fichier entier dans une boucle, puis remplacera la ou les nouvelles lignes par un espace.
Explication:
Créez une étiquette via :a.
Ajoutez la ligne actuelle et la ligne suivante à l'espace de motif via N.
Si nous sommes avant la dernière ligne, branchez-vous sur l'étiquette créée $!ba( $!signifie ne pas le faire sur la dernière ligne car il devrait y avoir une nouvelle ligne finale).
Enfin, la substitution remplace chaque nouvelle ligne par un espace sur l'espace de motif (qui est le fichier entier).
Voici une syntaxe compatible multiplateforme qui fonctionne avec BSD et OS X sed(selon le commentaire @Benjie ):
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file
Comme vous pouvez le voir, l'utilisation sedde ce problème autrement simple est problématique. Pour une solution plus simple et adéquate, consultez cette réponse .
@Arjan et Masi: OS X utilise BSD sedplutôt que GNU sed, il peut donc y avoir des différences subtiles (et pas si subtiles) entre les deux. C'est une douleur constante si vous travaillez sur des machines OS X et * nix. J'installe habituellement GNU coreutilset findutilssur OS X, et j'ignore les versions BSD.
Télémaque
50
Ce :an'est pas un registre, c'est une étiquette de branche. C'est une cible pour la bcommande * qui fonctionne comme "goto". L'appeler un registre implique que vous pouvez créer des emplacements de stockage. Il n'y a que deux "registres"; l'un est appelé "l'espace d'attente" que votre script n'utilise pas et l'autre est appelé "l'espace modèle". La Ncommande ajoute une nouvelle ligne et la ligne suivante du fichier d'entrée à l'espace de motif. [* Vous pouvez avoir plusieurs étiquettes et bcommandes. Si une bcommande sans caractère char est ajoutée, elle se ramifie à la fin du script pour lire la ligne suivante et boucler à nouveau.]
pause jusqu'à nouvel ordre.
108
Vous pouvez exécuter cette multiplateforme (c'est-à-dire sur Mac OS X) en exécutant séparément les commandes plutôt qu'en les séparant par des points-virgules: sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
Benjie
74
Pourquoi personne ne commente ce qu'est un désordre stupide (pas la réponse elle-même, mais le programme pour lequel la réponse proposée est la meilleure solution à un problème très simple). Sed ressemble à une voiture qui fonctionne généralement bien, mais si vous voulez conduire dans une rue voisine spécifique, la seule façon est de soulever la voiture avec un hélicoptère.
Ark-kun
12
Allez les amis - 261 votes positifs pour une solution folle et incompréhensible qui ne fonctionne pas ???? sed est un excellent outil pour des substitutions simples sur une seule ligne, pour tout le reste, utilisez simplement awk. Bon deuil ....
Ed Morton
1711
sedest destiné à être utilisé sur une entrée en ligne. Bien qu'il puisse faire ce dont vous avez besoin.
Une meilleure option ici consiste à utiliser la trcommande comme suit:
tr '\n' ' ' < input_filename
ou supprimez entièrement les caractères de nouvelle ligne:
tr -d '\n' < input.txt > output.txt
ou si vous avez la version GNU (avec ses longues options)
Sed est basé sur des lignes, il lui est donc difficile de saisir de nouvelles lignes.
Alexander Gladysh
191
sed fonctionne sur un "flux" d'entrées, mais il le comprend en segments délimités par des sauts de ligne. C'est un outil Unix, ce qui signifie qu'il fait très bien une chose. La seule chose est de "travailler sur un fichier en ligne". Le faire faire autre chose sera difficile et risque d'être bogué. La morale de l'histoire est: choisissez le bon outil. Un grand nombre de vos questions semblent prendre la forme "Comment puis-je faire en sorte que cet outil fasse quelque chose qu'il n'a jamais été censé faire?" Ces questions sont intéressantes, mais si elles se posent au cours de la résolution d'un problème réel, vous vous trompez probablement.
dmckee --- chaton ex-modérateur
7
@JBBrown trest un joyau souvent négligé pour la construction de pipelines.
dmckee --- chaton ex-modérateur
70
tr est génial, mais vous ne pouvez remplacer les sauts de ligne que par des caractères uniques. Vous devez utiliser un outil différent si vous souhaitez remplacer les sauts de ligne par une chaîne
Eddy
21
@Eddy - J'ai utilisé tr pour remplacer les nouvelles lignes par un caractère qui n'apparaissait pas dans le texte (j'ai utilisé backtick), puis sed pour remplacer le backtick par la chaîne que je voulais utiliser
rjohnston
494
Réponse rapide
sed ':a;N;$!ba;s/\n/ /g' file
: a créer une étiquette 'a'
N ajoute la ligne suivante à l'espace de motif
$! si ce n'est pas la dernière ligne , ba branche (allez à) étiquette 'a'
s remplacer , / \ n / regex pour la nouvelle ligne , / / par un espace , / g correspondance globale (autant de fois que possible)
sed effectuera une boucle à travers les étapes 1 à 3 jusqu'à ce qu'il atteigne la dernière ligne, pour que toutes les lignes tiennent dans l'espace du modèle où sed remplacera tous les \ n caractères
Alternatives
Toutes les alternatives, contrairement à sed, n'auront pas besoin d'atteindre la dernière ligne pour commencer le processus
avec bash , lent
while read line;do printf "%s""$line ";done< file
avec perl , vitesse semblable à sed
perl -p -e 's/\n/ /' file
avec tr , plus rapide que sed , peut remplacer par un seul caractère
tr '\n'' '< file
avec pâte , vitesse tr- like, peut remplacer par un seul caractère
paste -s -d ' ' file
avec vitesse awk , tr- like
awk 1 ORS=' ' file
Une autre alternative comme "echo $ (<fichier)" est lente, ne fonctionne que sur les petits fichiers et doit traiter le fichier entier pour commencer le processus.
5.10. Pourquoi ne puis-je pas faire correspondre ou supprimer une nouvelle ligne en utilisant la
séquence d' échappement \ n ? Pourquoi ne puis-je pas faire correspondre 2 lignes ou plus en utilisant \ n?
Le \ n ne correspondra jamais à la nouvelle ligne à la fin de la ligne car le
nouvelle ligne est toujours supprimée avant que la ligne ne soit placée dans l'
espace de motif. Pour obtenir 2 lignes ou plus dans l'espace de motif, utilisez
la commande 'N' ou quelque chose de similaire (comme 'H; ...; g;').
Sed fonctionne comme ceci: sed lit une ligne à la fois, coupe la
nouvelle ligne de fin, place ce qui reste dans l'espace de modèle où
le script sed peut l'adresser ou le modifier, et lorsque l'espace de modèle
est imprimé, ajoute une nouvelle ligne à stdout (ou vers un fichier). Si l'
espace de motif est entièrement ou partiellement supprimé avec 'd' ou 'D', la
nouvelle ligne n'est pas ajoutée dans de tels cas. Ainsi, des scripts comme
sed 's/\n//' file # to delete newlines from each line
sed 's/\n/foo\n/' file # to add a word to the end of each line
ne fonctionnera JAMAIS, car la nouvelle ligne de fin est supprimée avant que
la ligne ne soit placée dans l'espace de motif. Pour effectuer les tâches ci-dessus,
utilisez plutôt l'un de ces scripts:
tr -d '\n'< file # use tr to delete newlines
sed ':a;N;$!ba;s/\n//g' file # GNU sed to delete newlines
sed 's/$/ foo/' file # add "foo" to end of each line
Étant donné que les versions de sed autres que GNU sed ont des limites à la taille du
tampon de modèle, l'utilitaire «tr» d'Unix est préférable ici.
Si la dernière ligne du fichier contient une nouvelle ligne, GNU sed ajoutera
cette nouvelle ligne à la sortie mais supprimera toutes les autres, tandis que tr
supprimera toutes les nouvelles lignes.
Pour faire correspondre un bloc de deux lignes ou plus, il y a 3 choix de base:
(1) utilisez la commande «N» pour ajouter la ligne suivante à l'espace de motif;
(2) utilisez la commande «H» au moins deux fois pour ajouter la ligne actuelle
à l'espace d'attente, puis récupérez les lignes de l'espace d'attente
avec x, g ou G; ou (3) utiliser des plages d'adresses (voir section 3.3, ci-dessus)
pour faire correspondre les lignes entre deux adresses spécifiées.
Les choix (1) et (2) mettront un \ n dans l'espace modèle, où il
pourra être adressé comme souhaité ('s / ABC \ nXYZ / alphabet / g'). Un exemple
d'utilisation de «N» pour supprimer un bloc de lignes apparaît dans la section 4.13
(«Comment supprimer un bloc de lignes consécutives spécifiques ?»). Cet
exemple peut être modifié en remplaçant la commande delete par
autre chose , comme 'p' (impression), 'i' (insertion), 'c' (changement), 'a' (ajout),
ou 's' (remplacement) .
Choice (3) ne sera pas mettre \ n dans l'espace de travail , mais il ne
correspond un bloc de lignes consécutives, donc il se peut que vous n'avez pas
même besoin \ n pour trouver ce que vous cherchez. Depuis GNU sed
version 3.02.80 prend désormais en charge cette syntaxe:
sed '/start/,+4d'# to delete "start" plus the next 4 lines,
en plus des
adresses traditionnelles "/ d'ici /, / là-bas / {...}" , il peut être possible d'éviter complètement l'utilisation de \ n.
La meilleure partie de cette réponse est que la "réponse longue" explique exactement comment et pourquoi la commande fonctionne.
pdwalker
3
C'est peut-être la plus utile des milliers de réponses que j'ai lues sur stackexchange. J'ai besoin de faire correspondre plusieurs caractères sur plusieurs lignes. Aucun exemple sed précédent ne couvrait plusieurs lignes et tr ne peut pas gérer la correspondance de plusieurs caractères. Perl a l'air bien, mais ne fonctionne pas comme prévu. Je voterais cette réponse plusieurs fois si je le pouvais.
mightypile
225
Une alternative awk plus courte:
awk 1 ORS=' '
Explication
Un programme awk est constitué de règles qui consistent en des blocs de code conditionnels, c'est-à-dire:
condition { code-block }
Si le code-bloc est omis, la valeur par défaut est utilisé: { print $0 }. Ainsi, le 1est interprété comme une véritable condition etprint $0 est exécuté pour chaque ligne.
Lors de la awklecture de l'entrée, il la divise en enregistrements en fonction de la valeur de RS(Séparateur d'enregistrements), qui par défaut est une nouvelle ligne, awkanalysera donc par défaut l'entrée en ligne. Le fractionnement implique également la suppression RSde l'enregistrement d'entrée.
Maintenant, lors de l'impression d'un enregistrement, ORS(Séparateur d'enregistrements de sortie) lui est ajouté, la valeur par défaut est à nouveau une nouvelle ligne. Ainsi, en changeant ORSen espace, toutes les nouvelles lignes sont changées en espaces.
J'aime beaucoup cette solution simple, qui est beaucoup plus lisible que les autres
Fedir RYKHTIK
8
Si cela a plus de sens, cela pourrait effectivement s'écrire: awk 'BEGIN { ORS=" " } { print $0 } END { print "\n"} ' file.txt(en ajoutant un retour à la ligne de fin juste pour illustrer le début / la fin); le "1" est évalué pour true(traiter la ligne) et print(imprimer la ligne). Un conditionnel pourrait également être ajouté à cette expression, par exemple en ne travaillant que sur des lignes correspondant à un motif: awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n"} '
michael
2
Vous pouvez le faire plus simplement: codeawk 'ORS = ""' file.txtcode
Udi
Lorsque vous utilisez awk comme ceci, malheureusement, le dernier saut de ligne du fichier est également supprimé. Voir la réponse de Patrick Dark ci-dessus sur l'utilisation de 'tr' dans un sous-shell comme `cat file | echo $ (tr "\ 012" "") `qui fait l'affaire. Nifty.
Bernie Reiter
143
gnu sed a une option -zpour les enregistrements séparés par des valeurs nulles (lignes). Vous pouvez simplement appeler:
Même si l'entrée contient des valeurs nulles, elles seront conservées (en tant que délimiteurs d'enregistrement).
Toby Speight
6
Cela ne chargera-t-il pas toute l'entrée s'il n'y a pas de valeurs nulles? Dans ce cas, le traitement d'un fichier de plusieurs gigaoctets peut se bloquer.
Ruslan
3
@Ruslan, oui, il charge toute l'entrée. Cette solution n'est pas une bonne idée pour les fichiers de plusieurs gigaoctets.
JJoao
7
C'est vraiment la meilleure réponse. Les autres expressions sont trop déformées pour être mémorisées. @JJoao Vous pouvez l'utiliser avec -u, --unbuffered. Le manmage déclare: "charger des quantités minimales de données à partir des fichiers d'entrée et vider les tampons de sortie plus souvent".
not2qubit
donc. beaucoup. cette.
sjas
85
La version Perl fonctionne comme vous vous y attendiez.
perl -i -p -e 's/\n//' file
Comme indiqué dans les commentaires, il convient de noter que cette modification est en place. -i.bakvous donnera une sauvegarde du fichier d'origine avant le remplacement au cas où votre expression régulière ne serait pas aussi intelligente que vous le pensiez.
Veuillez au moins mentionner que -isans suffixe ne fait aucune sauvegarde . -i.bakvous protège d'une erreur simple et laide (par exemple, en oubliant de taper -pet en remettant à zéro le fichier).
Télémaque
6
@Telemachus: C'est un bon point, mais il peut être argumenté de toute façon. La principale raison pour laquelle je ne l'ai pas mentionné est que l'exemple sed dans la question de l'OP ne fait pas de sauvegardes, donc cela semble superflu ici. L'autre raison est que je n'ai jamais réellement utilisé la fonctionnalité de sauvegarde (je trouve les sauvegardes automatiques ennuyeuses, en fait), donc j'oublie toujours qu'elle est là. La troisième raison est que ma ligne de commande rallonge de quatre caractères. Pour le meilleur ou pour le pire (probablement pire), je suis un minimaliste compulsif; Je préfère juste la brièveté. Je sais que tu n'es pas d'accord. Je ferai de mon mieux pour ne pas oublier d'avertir des sauvegardes à l'avenir.
ire_and_curses
6
@Ire_and_curses: En fait, vous venez de faire un putain de bon argument pour m'ignorer. Autrement dit, vous avez des raisons pour vos choix, et si je suis d'accord ou non avec ces choix, je respecte certainement cela. Je ne sais pas trop pourquoi, mais j'ai été en larmes à propos de cette chose particulière récemment (le -idrapeau en Perl sans suffixe). Je suis sûr que je trouverai quelque chose d'autre à obséder assez tôt. :)
Télémaque
Il est vraiment regrettable que cela ne fonctionne pas avec stdin en spécifiant le -nom de fichier. Y-a-t-il un moyen de faire ça? C'est ma façon de ne pas vous soucier de modifier un fichier en utilisant un pipeline qui commence par cat.
Steven Lu
@StevenLu Perl lira par défaut à partir de STDIN si aucun nom de fichier n'est fourni. Vous pouvez donc faire par exempleperl -i -p -e 's/\n//' < infile > outfile
ire_and_curses
44
Qui a besoin sed? Voici le bashchemin:
cat test.txt | while read line; do echo -n "$line "; done
Upvote, j'ai normalement utilisé la première réponse, mais lorsque vous passez / dev / urandom à travers elle, sed n'imprimera pas avant EOF et ^ C n'est pas EOF. Cette solution s'imprime chaque fois qu'elle voit une nouvelle ligne. Exactement ce dont j'avais besoin! Merci!
Vasiliy Sharapov, le
1
alors pourquoi pas: echo -n `cat days.txt` De cet article
Tony
9
@Tony car les backticks sont obsolètes et le chat est redondant ;-) Utilisation: echo $ (<days.txt)
seumasmac
10
Sans même en utilisant cat: while read line; do echo -n "$line "; done < test.txt. Peut être utile si un sous-shell pose problème.
Carlo Cannas
5
echo $(<file)serre tous les espaces dans un seul espace, pas seulement les nouvelles lignes: cela va au-delà de ce que l'OP demande.
glenn jackman
27
Afin de remplacer tous les sauts de ligne par des espaces utilisant awk, sans lire tout le fichier en mémoire:
awk '{printf "%s ", $0}' inputfile
Si vous voulez une nouvelle ligne finale:
awk '{printf "%s ", $0} END {printf "\n"}' inputfile
Vous pouvez utiliser un caractère autre que l'espace:
awk '{printf "%s|", $0} END {printf "\n"}' inputfile
ou simplement tr -d '\n'si vous ne voulez pas ajouter d'espace
spuder
21
Trois choses.
tr(ou cat, etc.) n'est absolument pas nécessaire. (GNU) sedet (GNU) awk, lorsqu'ils sont combinés, peuvent effectuer 99,9% de tout traitement de texte dont vous avez besoin.
stream! = basé sur la ligne. edest un éditeur en ligne. sedn'est pas. Voir la conférence sed pour plus d'informations sur la différence. La plupart des gens confondent sedêtre basé sur les lignes car il est, par défaut, pas très gourmand dans sa correspondance de modèle pour les correspondances SIMPLES - par exemple, lors de la recherche de modèle et du remplacement par un ou deux caractères, il ne remplace par défaut que lors de la première correspondance il trouve (sauf indication contraire par la commande globale). Il n'y aurait même pas de commande globale si elle était basée sur les lignes plutôt que sur les flux, car elle n'évaluerait que les lignes à la fois. Essayez de courir ed; vous remarquerez la différence. edest assez utile si vous voulez parcourir des lignes spécifiques (comme dans une boucle for), mais la plupart du temps, vous le voudrez sed.
Cela étant dit,
sed -e '{:q;N;s/\n/ /g;t q}' file
fonctionne très bien dans GNU sedversion 4.2.1. La commande ci-dessus remplacera toutes les nouvelles lignes par des espaces. C'est moche et un peu lourd à taper, mais ça marche très bien. Les {}« s peuvent être laissés, car ils sont inclus uniquement pour des raisons de santé mentale.
En tant que personne qui en sait seulement assez sedpour faire des trucs de base, je dois dire que c'est plus que ce que vous pouvez faire sedmais plutôt combien il est facile de comprendre ce qui se passe. J'ai du mal à travailler avec, seddonc je préférerais une commande plus simple quand je peux l'utiliser.
Nate
En utilisant t qcomme saut conditionnel, cela fonctionne avec un modèle comme s/\n / /(pour joindre toutes les lignes qui commencent par un espace) sans lire tout le fichier en mémoire. Pratique lors de la transformation de fichiers de plusieurs mégaoctets.
SMShell
L'article que vous avez lié ne reflète pas ce que vous dites
hek2mgl
Ceci est presque 800 fois plus lent que la réponse acceptée pour les entrées de grande taille. Cela est dû au remplacement de chaque ligne sur une entrée de plus en plus importante.
Une note subtile sur la nomenclature: le caractère \000est communément appelé NUL(un L), et NULLest généralement utilisé lorsque l'on parle d'un pointeur zéro (en C / C ++).
Je ne suis pas un expert, mais je suppose que sedvous devez d'abord ajouter la ligne suivante dans l'espace de motif, en utilisant " N". De la section "Multiline Pattern Space" dans "Advanced sed Commands" du livre sed & awk (Dale Dougherty et Arnold Robbins; O'Reilly 1997; page 107 dans l'aperçu ):
La commande multiligne suivante (N) crée un espace de modèle multiligne en lisant une nouvelle ligne d'entrée et en l'ajoutant au contenu de l'espace de modèle. Le contenu d'origine de l'espace de motif et la nouvelle ligne d'entrée sont séparés par une nouvelle ligne. Le caractère de nouvelle ligne incorporé peut être mis en correspondance dans les modèles par la séquence d'échappement "\ n". Dans un espace de modèle multiligne, le métacaractère "^" correspond au tout premier caractère de l'espace de modèle, et non au (x) caractère (s) suivant un ou des sauts de ligne incorporés. De même, "$" ne correspond qu'à la nouvelle ligne finale dans l'espace de motif, et non à aucune nouvelle ligne incorporée. Une fois la commande Next exécutée, le contrôle est ensuite passé aux commandes suivantes du script.
De man sed:
[2addr] N
Ajoutez la ligne d'entrée suivante à l'espace de motif, à l'aide d'un caractère de nouvelle ligne incorporé pour séparer le matériau ajouté du contenu d'origine. Notez que le numéro de ligne actuel change.
Je l'ai utilisé pour rechercher (plusieurs) fichiers journaux mal formatés, dans lesquels la chaîne de recherche peut être trouvée sur une ligne suivante "orpheline".
J'ai utilisé une approche hybride pour contourner la nouvelle ligne en utilisant tr pour remplacer les nouvelles lignes par des tabulations, puis en remplaçant les tabulations par ce que je veux. Dans ce cas, " " car j'essaie de générer des ruptures HTML.
Sous Windows, vous devrez probablement utiliser tr "\n" " " < input. Le shell Windows (cmd.exe) ne traite pas l'apostrophe comme un caractère de citation.
Keith Thompson
Non, dans le sous-système Windows 10 Ubuntu, vous devez utilisertr "\n\r" " " < input.txt > output.txt
user1491819
Cela fonctionne sur Windows 10 à l' aide GnuWin32: cat SourceFile.txt | tr --delete '\r\n' > OutputFile.txt. Ou, au lieu de Gnuwin32, utilisez Gow (Gnu sur Windows), github.com/bmatzelle/gow/wiki
Alchemistmatt
5
Solution pare-balles. Sécuritaire pour les données binaires et compatible POSIX, mais lent.
POSIX sed
nécessite une entrée conformément au
fichier texte POSIX
et aux
définitions de ligne POSIX , donc les octets NULS et les lignes trop longues ne sont pas autorisés et chaque ligne doit se terminer par une nouvelle ligne (y compris la dernière ligne). Cela rend difficile l'utilisation de sed pour le traitement de données d'entrée arbitraires.
La solution suivante évite sed et convertit à la place les octets d'entrée en codes octaux puis en octets à nouveau, mais intercepte le code octal 012 (nouvelle ligne) et sort la chaîne de remplacement à la place. Pour autant que je sache, la solution est compatible POSIX, elle devrait donc fonctionner sur une grande variété de plates-formes.
od -A n -t o1 -v | tr ' \t' '\n\n' | grep . |
while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done
Les deux read, [et printfsont intégrés dans au moins bash, mais ce n'est probablement pas garanti par POSIX, donc sur certaines plateformes, il se pourrait que chaque octet d'entrée démarre un ou plusieurs nouveaux processus, ce qui ralentira les choses. Même en bash, cette solution n'atteint qu'environ 50 kB / s, elle n'est donc pas adaptée aux gros fichiers.
Testé sur Ubuntu (bash, dash et busybox), FreeBSD et OpenBSD.
Dans certaines situations, vous pouvez peut-être changer RSpour une autre chaîne ou un autre caractère. De cette façon, \ n est disponible pour sub / gsub:
Le pouvoir des scripts shell est que si vous ne savez pas comment le faire d'une manière, vous pouvez le faire d'une autre manière. Et bien des fois, vous avez plus de choses à prendre en compte que de trouver une solution complexe à un problème simple.
Concernant la chose que gawk est lent ... et lit le fichier en mémoire, je ne sais pas, mais pour moi gawk semble fonctionner avec une ligne à la fois et est très très rapide (pas aussi rapide que certains des autres) , mais le temps d’écrire et de tester compte aussi).
Je traite des Mo et même des Go de données, et la seule limite que j'ai trouvée est la taille de la ligne.
Cela remplace [par un espace, et \rpar un espace, et \npar un espace, et ]par un espace. tr -d '\r\n' <filesupprimerait tout \rou plusieurs \ncaractères, mais ce n'est pas non plus ce qui est demandé. tr -d '\r' <filesupprimera tous les \rcaractères (qu'ils soient adjacents ou non \n) ce qui est probablement plus proche d'être utile ainsi que très probablement correct pour les besoins de l'OP (en supposant toujours que vous trcompreniez cette notation barre oblique inverse).
tripleee
4
Vous pouvez utiliser xargs- il remplacera \npar un espace par défaut.
Cependant, il y aurait des problèmes si votre entrée a un cas particulier unterminated quote, par exemple si les signes de citation sur une ligne donnée ne correspondent pas.
Vous avez raison désolé, j'ai oublié le fin printf
edi9999
c'était la seule approche qui fonctionnait pour moi dans git bash pour windows
Platon
3
Sous Mac OS X (avec FreeBSD sed):
# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta
Vous n'avez pas besoin d'échapper aux guillemets et au signe dollar si vous changez les guillemets extérieurs en guillemets simples. La lettre "o" est généralement considérée comme un mauvais choix comme nom de variable car elle peut être confondue avec le chiffre "0". Vous n'avez pas non plus besoin d'initialiser votre variable, il s'agit par défaut d'une chaîne nulle. Toutefois, si vous ne voulez pas un espace de premier plan étrangers: awk '{s = s sp $0; sp = " "} END {print s}'. Cependant, voir ma réponse pour un moyen d'utiliser awk sans lire le fichier entier en mémoire.
pause jusqu'à nouvel ordre.
Veuillez plutôt vérifier la réponse de Thor . Il est beaucoup plus efficace, lisible et juste mieux par tous les moyens à cette approche par rapport (même si cela ne fonctionne)!
mschilli
Mec, je comprends. Pas besoin de me le frotter au visage :-) La réponse de Thor est de toute façon bien au dessus sur la page (ce qui est vrai), alors qu'importe!
kralyk
3
Une solution que j'aime particulièrement est d'ajouter tout le fichier dans l'espace d'attente et de remplacer tous les sauts de ligne à la fin du fichier:
$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar
Cependant, quelqu'un m'a dit que l'espace d'attente peut être limité dans certaines implémentations sed.
le remplacement par une chaîne vide dans votre réponse masque le fait que toujours utiliser H pour ajouter à l'espace d'attente signifie que l'espace d'attente commencera par une nouvelle ligne. Pour éviter cela, vous devez utiliser1h;2,$H;${x;s/\n/x/g;p}
Jeff
3
Remplacez les sauts de ligne par n'importe quelle chaîne et remplacez également le dernier saut de ligne
Les trsolutions pures ne peuvent être remplacées que par un seul caractère, et les sedsolutions pures ne remplacent pas la dernière nouvelle ligne de l'entrée. La solution suivante résout ces problèmes et semble sûre pour les données binaires (même avec un environnement local UTF-8):
printf '1\n2\n3\n' |
sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'
C'est mauvais car cela produira une sortie indésirable sur toute entrée contenant@
Steven Lu
@StevenLu: Non, @l'entrée est OK. Il s'échappe %aet revient. La solution n'est peut-être pas complètement compatible POSIX, cependant (les octets NULL ne sont pas autorisés, donc pas bon pour les données binaires, et toutes les lignes doivent se terminer par un retour à la ligne afin que la trsortie ne soit pas vraiment valide).
Håkon A. Hjortland
Ah. Je vois que tu l'as réparé. Un peu compliqué pour ce qui devrait être une opération simple, mais un bon travail.
Steven Lu
3
C'est sed qui introduit les nouvelles lignes après substitution "normale". Tout d'abord, il coupe le caractère de nouvelle ligne, puis il traite selon vos instructions, puis il introduit une nouvelle ligne.
En utilisant sed, vous pouvez remplacer "la fin" d'une ligne (pas le caractère de nouvelle ligne) après avoir été coupé, avec une chaîne de votre choix, pour chaque ligne d'entrée; mais sed produira différentes lignes. Par exemple, supposons que vous vouliez remplacer la "fin de ligne" par "===" (plus général qu'un remplacement par un seul espace):
PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF
first line===
second line===
3rd line===
PROMPT~$
Pour remplacer le caractère de nouvelle ligne par la chaîne, vous pouvez, de manière inefficace, utiliser tr , comme indiqué précédemment, pour remplacer les caractères de nouvelle ligne par un "caractère spécial", puis utiliser sed pour remplacer ce caractère spécial par la chaîne que vous souhaitez .
Par exemple:
PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF
first line===second line===3rd line===PROMPT~$
x - which is used to exchange the data from both space (pattern and hold).
G - which is used to append the data from hold space to pattern space.
h - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
available in pattern space.
$!d - Clear the pattern space every time before getting next line until the
last line.
Flux:
Lorsque la première ligne provient de l'entrée, l'échange est effectué, donc 1 va pour conserver l'espace et \ n vient pour l'espace de motif, puis ajouter l'espace de maintien à l'espace de motif, puis la substitution est effectuée et supprimé l'espace de motif.
Au cours de la deuxième ligne, un échange est effectué, 2 va à l'espace de maintien et 1 vient à l'espace de motif, puis Gajoutez l'espace de maintien dans l'espace de motif, puish copiez le motif et la substitution est effectuée et supprimée. Cette opération se poursuit jusqu'à ce que eof soit atteint puis imprime le résultat exact.
Cependant, soyez averti que cela se echo 'Y' | sed 'x;G;1!h;s/\n/X/g;$!d'traduit par XY.
Spooky
3
Une autre GNUsed méthode, presque le même que Zsolt Botykai 's réponse , mais cette utilisation sedde s moins fréquemment utilisés y( transliterate de commande), qui enregistre un octet de code (la fuite g):
sed ':a;N;$!ba;y/\n/ /'
On pourrait espérer yfonctionner plus vite que s, (peut-être à des trvitesses 20 fois plus rapides), mais dans GNU sed v4.2.2y est environ 4% plus lent que s.
tr
n'est le bon outil pour le travail que si remplacer un seul caractère par un seul caractère, tandis que l'exemple ci-dessus montre remplacer la nouvelle ligne par un espace. Donc dans l'exemple ci-dessus, tr pourrait fonctionner .. Mais serait limitant plus tard.tr
dans le bon outil pour le travail parce que le questionneur voulait remplacer chaque nouvelle ligne par un espace, comme le montre son exemple. Le remplacement des sauts de ligne est uniquement mystérieuxsed
mais facile à réalisertr
. C'est une question courante. Effectuer des remplacements de regex ne se fait pas partr
mais parsed
, ce qui serait le bon outil ... pour une question différente.tr '\012' ' '
avec unecho
. Sinon, le dernier saut de ligne du fichier est également supprimé.tr '\012' ' ' < filename; echo
fait l'affaire.Réponses:
Utilisez cette solution avec GNU
sed
:Cela lira le fichier entier dans une boucle, puis remplacera la ou les nouvelles lignes par un espace.
Explication:
:a
.N
.$!ba
($!
signifie ne pas le faire sur la dernière ligne car il devrait y avoir une nouvelle ligne finale).Voici une syntaxe compatible multiplateforme qui fonctionne avec BSD et OS X
sed
(selon le commentaire @Benjie ):Comme vous pouvez le voir, l'utilisation
sed
de ce problème autrement simple est problématique. Pour une solution plus simple et adéquate, consultez cette réponse .la source
sed
plutôt que GNUsed
, il peut donc y avoir des différences subtiles (et pas si subtiles) entre les deux. C'est une douleur constante si vous travaillez sur des machines OS X et * nix. J'installe habituellement GNUcoreutils
etfindutils
sur OS X, et j'ignore les versions BSD.:a
n'est pas un registre, c'est une étiquette de branche. C'est une cible pour lab
commande * qui fonctionne comme "goto". L'appeler un registre implique que vous pouvez créer des emplacements de stockage. Il n'y a que deux "registres"; l'un est appelé "l'espace d'attente" que votre script n'utilise pas et l'autre est appelé "l'espace modèle". LaN
commande ajoute une nouvelle ligne et la ligne suivante du fichier d'entrée à l'espace de motif. [* Vous pouvez avoir plusieurs étiquettes etb
commandes. Si uneb
commande sans caractère char est ajoutée, elle se ramifie à la fin du script pour lire la ligne suivante et boucler à nouveau.]sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
sed
est destiné à être utilisé sur une entrée en ligne. Bien qu'il puisse faire ce dont vous avez besoin.Une meilleure option ici consiste à utiliser la
tr
commande comme suit:ou supprimez entièrement les caractères de nouvelle ligne:
ou si vous avez la version GNU (avec ses longues options)
la source
tr
est un joyau souvent négligé pour la construction de pipelines.Réponse rapide
sed effectuera une boucle à travers les étapes 1 à 3 jusqu'à ce qu'il atteigne la dernière ligne, pour que toutes les lignes tiennent dans l'espace du modèle où sed remplacera tous les \ n caractères
Alternatives
Toutes les alternatives, contrairement à sed, n'auront pas besoin d'atteindre la dernière ligne pour commencer le processus
avec bash , lent
avec perl , vitesse semblable à sed
avec tr , plus rapide que sed , peut remplacer par un seul caractère
avec pâte , vitesse tr- like, peut remplacer par un seul caractère
avec vitesse awk , tr- like
Une autre alternative comme "echo $ (<fichier)" est lente, ne fonctionne que sur les petits fichiers et doit traiter le fichier entier pour commencer le processus.
Réponse longue de la FAQ sed 5.10
5.10. Pourquoi ne puis-je pas faire correspondre ou supprimer une nouvelle ligne en utilisant la
séquence d' échappement \ n ? Pourquoi ne puis-je pas faire correspondre 2 lignes ou plus en utilisant \ n?
Le \ n ne correspondra jamais à la nouvelle ligne à la fin de la ligne car le
nouvelle ligne est toujours supprimée avant que la ligne ne soit placée dans l'
espace de motif. Pour obtenir 2 lignes ou plus dans l'espace de motif, utilisez
la commande 'N' ou quelque chose de similaire (comme 'H; ...; g;').
Sed fonctionne comme ceci: sed lit une ligne à la fois, coupe la
nouvelle ligne de fin, place ce qui reste dans l'espace de modèle où
le script sed peut l'adresser ou le modifier, et lorsque l'espace de modèle
est imprimé, ajoute une nouvelle ligne à stdout (ou vers un fichier). Si l'
espace de motif est entièrement ou partiellement supprimé avec 'd' ou 'D', la
nouvelle ligne n'est pas ajoutée dans de tels cas. Ainsi, des scripts comme
ne fonctionnera JAMAIS, car la nouvelle ligne de fin est supprimée avant que
la ligne ne soit placée dans l'espace de motif. Pour effectuer les tâches ci-dessus,
utilisez plutôt l'un de ces scripts:
Étant donné que les versions de sed autres que GNU sed ont des limites à la taille du
tampon de modèle, l'utilitaire «tr» d'Unix est préférable ici.
Si la dernière ligne du fichier contient une nouvelle ligne, GNU sed ajoutera
cette nouvelle ligne à la sortie mais supprimera toutes les autres, tandis que tr
supprimera toutes les nouvelles lignes.
Pour faire correspondre un bloc de deux lignes ou plus, il y a 3 choix de base:
(1) utilisez la commande «N» pour ajouter la ligne suivante à l'espace de motif;
(2) utilisez la commande «H» au moins deux fois pour ajouter la ligne actuelle
à l'espace d'attente, puis récupérez les lignes de l'espace d'attente
avec x, g ou G; ou (3) utiliser des plages d'adresses (voir section 3.3, ci-dessus)
pour faire correspondre les lignes entre deux adresses spécifiées.
Les choix (1) et (2) mettront un \ n dans l'espace modèle, où il
pourra être adressé comme souhaité ('s / ABC \ nXYZ / alphabet / g'). Un exemple
d'utilisation de «N» pour supprimer un bloc de lignes apparaît dans la section 4.13
(«Comment supprimer un bloc de lignes consécutives spécifiques ?»). Cet
exemple peut être modifié en remplaçant la commande delete par
autre chose , comme 'p' (impression), 'i' (insertion), 'c' (changement), 'a' (ajout),
ou 's' (remplacement) .
Choice (3) ne sera pas mettre \ n dans l'espace de travail , mais il ne
correspond un bloc de lignes consécutives, donc il se peut que vous n'avez pas
même besoin \ n pour trouver ce que vous cherchez. Depuis GNU sed
version 3.02.80 prend désormais en charge cette syntaxe:
en plus des
adresses traditionnelles "/ d'ici /, / là-bas / {...}" , il peut être possible d'éviter complètement l'utilisation de \ n.
la source
tr
était une excellente idée, et votre couverture globale en fait une réponse de qualité supérieure.paste
... et tous les autres!Une alternative awk plus courte:
Explication
Un programme awk est constitué de règles qui consistent en des blocs de code conditionnels, c'est-à-dire:
Si le code-bloc est omis, la valeur par défaut est utilisé:
{ print $0 }
. Ainsi, le1
est interprété comme une véritable condition etprint $0
est exécuté pour chaque ligne.Lors de la
awk
lecture de l'entrée, il la divise en enregistrements en fonction de la valeur deRS
(Séparateur d'enregistrements), qui par défaut est une nouvelle ligne,awk
analysera donc par défaut l'entrée en ligne. Le fractionnement implique également la suppressionRS
de l'enregistrement d'entrée.Maintenant, lors de l'impression d'un enregistrement,
ORS
(Séparateur d'enregistrements de sortie) lui est ajouté, la valeur par défaut est à nouveau une nouvelle ligne. Ainsi, en changeantORS
en espace, toutes les nouvelles lignes sont changées en espaces.la source
awk 'BEGIN { ORS=" " } { print $0 } END { print "\n"} ' file.txt
(en ajoutant un retour à la ligne de fin juste pour illustrer le début / la fin); le "1" est évalué pourtrue
(traiter la ligne) etprint
(imprimer la ligne). Un conditionnel pourrait également être ajouté à cette expression, par exemple en ne travaillant que sur des lignes correspondant à un motif:awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n"} '
code
awk 'ORS = ""' file.txtcode
gnu sed a une option
-z
pour les enregistrements séparés par des valeurs nulles (lignes). Vous pouvez simplement appeler:la source
-u, --unbuffered
. Leman
mage déclare: "charger des quantités minimales de données à partir des fichiers d'entrée et vider les tampons de sortie plus souvent".La version Perl fonctionne comme vous vous y attendiez.
Comme indiqué dans les commentaires, il convient de noter que cette modification est en place.
-i.bak
vous donnera une sauvegarde du fichier d'origine avant le remplacement au cas où votre expression régulière ne serait pas aussi intelligente que vous le pensiez.la source
-i
sans suffixe ne fait aucune sauvegarde .-i.bak
vous protège d'une erreur simple et laide (par exemple, en oubliant de taper-p
et en remettant à zéro le fichier).-i
drapeau en Perl sans suffixe). Je suis sûr que je trouverai quelque chose d'autre à obséder assez tôt. :)-
nom de fichier. Y-a-t-il un moyen de faire ça? C'est ma façon de ne pas vous soucier de modifier un fichier en utilisant un pipeline qui commence par cat.perl -i -p -e 's/\n//' < infile > outfile
Qui a besoin
sed
? Voici lebash
chemin:la source
cat
:while read line; do echo -n "$line "; done < test.txt
. Peut être utile si un sous-shell pose problème.echo $(<file)
serre tous les espaces dans un seul espace, pas seulement les nouvelles lignes: cela va au-delà de ce que l'OP demande.Afin de remplacer tous les sauts de ligne par des espaces utilisant awk, sans lire tout le fichier en mémoire:
Si vous voulez une nouvelle ligne finale:
Vous pouvez utiliser un caractère autre que l'espace:
la source
END{ print ""}
est une alternative plus courte pour une nouvelle ligne de fin.est la commande.
Simple et facile à utiliser.
la source
tr -d '\n'
si vous ne voulez pas ajouter d'espaceTrois choses.
tr
(oucat
, etc.) n'est absolument pas nécessaire. (GNU)sed
et (GNU)awk
, lorsqu'ils sont combinés, peuvent effectuer 99,9% de tout traitement de texte dont vous avez besoin.stream! = basé sur la ligne.
ed
est un éditeur en ligne.sed
n'est pas. Voir la conférence sed pour plus d'informations sur la différence. La plupart des gens confondentsed
être basé sur les lignes car il est, par défaut, pas très gourmand dans sa correspondance de modèle pour les correspondances SIMPLES - par exemple, lors de la recherche de modèle et du remplacement par un ou deux caractères, il ne remplace par défaut que lors de la première correspondance il trouve (sauf indication contraire par la commande globale). Il n'y aurait même pas de commande globale si elle était basée sur les lignes plutôt que sur les flux, car elle n'évaluerait que les lignes à la fois. Essayez de courired
; vous remarquerez la différence.ed
est assez utile si vous voulez parcourir des lignes spécifiques (comme dans une boucle for), mais la plupart du temps, vous le voudrezsed
.Cela étant dit,
fonctionne très bien dans GNU
sed
version 4.2.1. La commande ci-dessus remplacera toutes les nouvelles lignes par des espaces. C'est moche et un peu lourd à taper, mais ça marche très bien. Les{}
« s peuvent être laissés, car ils sont inclus uniquement pour des raisons de santé mentale.la source
sed
pour faire des trucs de base, je dois dire que c'est plus que ce que vous pouvez fairesed
mais plutôt combien il est facile de comprendre ce qui se passe. J'ai du mal à travailler avec,sed
donc je préférerais une commande plus simple quand je peux l'utiliser.t q
comme saut conditionnel, cela fonctionne avec un modèle commes/\n / /
(pour joindre toutes les lignes qui commencent par un espace) sans lire tout le fichier en mémoire. Pratique lors de la transformation de fichiers de plusieurs mégaoctets.La réponse avec: une étiquette ...
Comment remplacer une nouvelle ligne (\ n) en utilisant sed?
... ne fonctionne pas dans freebsd 7.2 sur la ligne de commande:
Mais si vous mettez le script sed dans un fichier ou utilisez -e pour "construire" le script sed ...
ou ...
Peut-être que le sed dans OS X est similaire.
la source
Solution facile à comprendre
J'ai eu ce problème. Le kicker était que j'avais besoin de la solution pour travailler sur BSD (Mac OS X) et GNU (Linux et Cygwin )
sed
ettr
:Production:
(a une nouvelle ligne de fin)
Il fonctionne sous Linux, OS X et BSD - même sans support UTF-8 ou avec un terminal merdique.
Utilisez
tr
pour échanger la nouvelle ligne avec un autre caractère.NULL
(\000
ou\x00
) est agréable car il n'a pas besoin de support UTF-8 et il est peu probable qu'il soit utilisé.Utilisez
sed
pour faire correspondre leNULL
Utilisez
tr
pour échanger des nouvelles lignes supplémentaires si vous en avez besoinla source
\000
est communément appeléNUL
(un L), etNULL
est généralement utilisé lorsque l'on parle d'un pointeur zéro (en C / C ++).Vous pouvez utiliser des xargs :
ou
la source
xargs < file.txt
Je ne suis pas un expert, mais je suppose que
sed
vous devez d'abord ajouter la ligne suivante dans l'espace de motif, en utilisant "N
". De la section "Multiline Pattern Space" dans "Advanced sed Commands" du livre sed & awk (Dale Dougherty et Arnold Robbins; O'Reilly 1997; page 107 dans l'aperçu ):De
man sed
:Je l'ai utilisé pour rechercher (plusieurs) fichiers journaux mal formatés, dans lesquels la chaîne de recherche peut être trouvée sur une ligne suivante "orpheline".
la source
J'ai utilisé une approche hybride pour contourner la nouvelle ligne en utilisant tr pour remplacer les nouvelles lignes par des tabulations, puis en remplaçant les tabulations par ce que je veux. Dans ce cas, "
" car j'essaie de générer des ruptures HTML.
la source
En réponse à la solution "tr" ci-dessus, sous Windows (utilisant probablement la version Gnuwin32 de tr), la solution proposée:
ne fonctionnait pas pour moi, ce serait une erreur ou remplacer réellement le \ nw / '' pour une raison quelconque.
En utilisant une autre fonctionnalité de tr, l'option "supprimer" -d a bien fonctionné:
ou '\ r \ n' au lieu de '\ n'
la source
tr "\n" " " < input
. Le shell Windows (cmd.exe) ne traite pas l'apostrophe comme un caractère de citation.tr "\n\r" " " < input.txt > output.txt
cat SourceFile.txt | tr --delete '\r\n' > OutputFile.txt
. Ou, au lieu de Gnuwin32, utilisez Gow (Gnu sur Windows), github.com/bmatzelle/gow/wikiSolution pare-balles. Sécuritaire pour les données binaires et compatible POSIX, mais lent.
POSIX sed nécessite une entrée conformément au fichier texte POSIX et aux définitions de ligne POSIX , donc les octets NULS et les lignes trop longues ne sont pas autorisés et chaque ligne doit se terminer par une nouvelle ligne (y compris la dernière ligne). Cela rend difficile l'utilisation de sed pour le traitement de données d'entrée arbitraires.
La solution suivante évite sed et convertit à la place les octets d'entrée en codes octaux puis en octets à nouveau, mais intercepte le code octal 012 (nouvelle ligne) et sort la chaîne de remplacement à la place. Pour autant que je sache, la solution est compatible POSIX, elle devrait donc fonctionner sur une grande variété de plates-formes.
Documentation de référence POSIX: sh , langage de commande shell , od , tr , grep , read , [ , printf .
Les deux
read
,[
etprintf
sont intégrés dans au moins bash, mais ce n'est probablement pas garanti par POSIX, donc sur certaines plateformes, il se pourrait que chaque octet d'entrée démarre un ou plusieurs nouveaux processus, ce qui ralentira les choses. Même en bash, cette solution n'atteint qu'environ 50 kB / s, elle n'est donc pas adaptée aux gros fichiers.Testé sur Ubuntu (bash, dash et busybox), FreeBSD et OpenBSD.
la source
Dans certaines situations, vous pouvez peut-être changer
RS
pour une autre chaîne ou un autre caractère. De cette façon, \ n est disponible pour sub / gsub:Le pouvoir des scripts shell est que si vous ne savez pas comment le faire d'une manière, vous pouvez le faire d'une autre manière. Et bien des fois, vous avez plus de choses à prendre en compte que de trouver une solution complexe à un problème simple.
Concernant la chose que gawk est lent ... et lit le fichier en mémoire, je ne sais pas, mais pour moi gawk semble fonctionner avec une ligne à la fois et est très très rapide (pas aussi rapide que certains des autres) , mais le temps d’écrire et de tester compte aussi).
Je traite des Mo et même des Go de données, et la seule limite que j'ai trouvée est la taille de la ligne.
la source
Si vous avez la malchance de devoir gérer les fins de ligne Windows, vous devez supprimer le
\r
et le\n
la source
[
par un espace, et\r
par un espace, et\n
par un espace, et]
par un espace.tr -d '\r\n' <file
supprimerait tout\r
ou plusieurs\n
caractères, mais ce n'est pas non plus ce qui est demandé.tr -d '\r' <file
supprimera tous les\r
caractères (qu'ils soient adjacents ou non\n
) ce qui est probablement plus proche d'être utile ainsi que très probablement correct pour les besoins de l'OP (en supposant toujours que voustr
compreniez cette notation barre oblique inverse).Vous pouvez utiliser
xargs
- il remplacera\n
par un espace par défaut.Cependant, il y aurait des problèmes si votre entrée a un cas particulier
unterminated quote
, par exemple si les signes de citation sur une ligne donnée ne correspondent pas.la source
Recherche et remplace à l'aide de l'autorisation \ n
Devient
la source
Pourquoi n'ai-je pas trouvé de solution simple
awk
?printf
imprimera chaque ligne sans retour à la ligne, si vous souhaitez séparer les lignes originales par un espace ou autre:la source
echo "1\n2\n3" | awk '{printf $0}'
, cela fonctionne pour moi. @ edi9999f
in printfSous Mac OS X (avec FreeBSD sed):
la source
Pour supprimer des lignes vides:
la source
sed: 1: "s/^$//;t;p;": undefined label ';p;'
.Utilisation d'Awk:
la source
awk '{s = s sp $0; sp = " "} END {print s}'
. Cependant, voir ma réponse pour un moyen d'utiliser awk sans lire le fichier entier en mémoire.Une solution que j'aime particulièrement est d'ajouter tout le fichier dans l'espace d'attente et de remplacer tous les sauts de ligne à la fin du fichier:
Cependant, quelqu'un m'a dit que l'espace d'attente peut être limité dans certaines implémentations sed.
la source
1h;2,$H;${x;s/\n/x/g;p}
Remplacez les sauts de ligne par n'importe quelle chaîne et remplacez également le dernier saut de ligne
Les
tr
solutions pures ne peuvent être remplacées que par un seul caractère, et lessed
solutions pures ne remplacent pas la dernière nouvelle ligne de l'entrée. La solution suivante résout ces problèmes et semble sûre pour les données binaires (même avec un environnement local UTF-8):Résultat:
la source
@
@
l'entrée est OK. Il s'échappe%a
et revient. La solution n'est peut-être pas complètement compatible POSIX, cependant (les octets NULL ne sont pas autorisés, donc pas bon pour les données binaires, et toutes les lignes doivent se terminer par un retour à la ligne afin que latr
sortie ne soit pas vraiment valide).C'est sed qui introduit les nouvelles lignes après substitution "normale". Tout d'abord, il coupe le caractère de nouvelle ligne, puis il traite selon vos instructions, puis il introduit une nouvelle ligne.
En utilisant sed, vous pouvez remplacer "la fin" d'une ligne (pas le caractère de nouvelle ligne) après avoir été coupé, avec une chaîne de votre choix, pour chaque ligne d'entrée; mais sed produira différentes lignes. Par exemple, supposons que vous vouliez remplacer la "fin de ligne" par "===" (plus général qu'un remplacement par un seul espace):
Pour remplacer le caractère de nouvelle ligne par la chaîne, vous pouvez, de manière inefficace, utiliser tr , comme indiqué précédemment, pour remplacer les caractères de nouvelle ligne par un "caractère spécial", puis utiliser sed pour remplacer ce caractère spécial par la chaîne que vous souhaitez .
Par exemple:
la source
Vous pouvez également utiliser cette méthode
Explication
Flux:
Lorsque la première ligne provient de l'entrée, l'échange est effectué, donc 1 va pour conserver l'espace et \ n vient pour l'espace de motif, puis ajouter l'espace de maintien à l'espace de motif, puis la substitution est effectuée et supprimé l'espace de motif.
Au cours de la deuxième ligne, un échange est effectué, 2 va à l'espace de maintien et 1 vient à l'espace de motif, puis
G
ajoutez l'espace de maintien dans l'espace de motif, puish
copiez le motif et la substitution est effectuée et supprimée. Cette opération se poursuit jusqu'à ce que eof soit atteint puis imprime le résultat exact.la source
echo 'Y' | sed 'x;G;1!h;s/\n/X/g;$!d'
traduit parXY
.Une autre GNU
sed
méthode, presque le même que Zsolt Botykai 's réponse , mais cette utilisationsed
de s moins fréquemment utilisésy
( transliterate de commande), qui enregistre un octet de code (la fuiteg
):On pourrait espérer
y
fonctionner plus vite ques
, (peut-être à destr
vitesses 20 fois plus rapides), mais dans GNU sed v4.2.2y
est environ 4% plus lent ques
.Version BSD plus portable
sed
:la source
y
est environ 15% plus rapide. Voir cette réponse pour un exemple de travail.sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'
serait donc la voie à suivre.