Comment insérer une nouvelle ligne avant un motif dans une ligne?
Par exemple, cela insérera une nouvelle ligne derrière le modèle regex.
sed 's/regex/&\n/g'
Comment puis-je faire la même chose mais devant le motif?
Étant donné cet exemple de fichier d'entrée, le modèle à associer est le numéro de téléphone.
some text (012)345-6789
Devrait devenir
some text
(012)345-6789
sed '/regex/G'
Réponses:
Cela fonctionne sous
bash
etzsh
, testé sur Linux et OS X:En général, pour
$
suivi d'un littéral de chaîne entre guillemets simplesbash
effectue une substitution de barre oblique inverse de style C, par exemple$'\t'
est traduit en une tabulation littérale. De plus, sed veut que votre littéral de nouvelle ligne soit échappé avec une barre oblique inverse, d'où l'\
avant$
. Et enfin, le signe dollar lui-même ne doit pas être cité pour qu'il soit interprété par le shell, donc nous fermons la cotation avant le$
puis l'ouvrons à nouveau.Edit : Comme suggéré dans les commentaires de @ mklement0, cela fonctionne également:
Ce qui se passe ici est: la commande sed entière est maintenant une chaîne de style C, ce qui signifie que la barre oblique inverse que sed doit être placée avant le nouveau littéral de ligne doit maintenant être échappée avec une autre barre oblique inverse. Bien que plus lisible, dans ce cas, vous ne serez pas en mesure de faire des substitutions de chaînes shell (sans le rendre à nouveau laid.)
la source
sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'
. Notez les deux guillemets simples après le \ n. Le premier ferme la$
section " " de sorte que le reste de la ligne n'en soit pas affecté. Sans ces guillemets, le \ 2 a été ignoré.sed $'s/regexp/\\\n/g'
qui améliore la lisibilité - la seule mise en garde est que vous devez alors doubler tous les littéraux\
caractères.Certaines des autres réponses n'ont pas fonctionné pour ma version de sed. Changer la position de
&
et\n
a fonctionné.Edit: Cela ne semble pas fonctionner sur OS X, sauf si vous installez
gnu-sed
.la source
brew install gnu-sed
suivi degsed 's/regexp/\n&/g'
echo 'alias sed=gsed' >> ~/.bashrc
Dans sed, vous ne pouvez pas facilement ajouter de nouvelles lignes dans le flux de sortie. Vous devez utiliser une ligne de continuation, ce qui est gênant, mais cela fonctionne:
Exemple:
Voir ici pour plus de détails. Si vous voulez quelque chose d'un peu moins gênant, vous pouvez essayer d'utiliser
perl -pe
avec des groupes de correspondance au lieu de sed:$1
fait référence au premier groupe correspondant dans l'expression régulière, où les groupes sont entre parenthèses.la source
perl -pi -e 's/(.*)/\n$1/' foo
s
appel de fonction (contrairement à l' implémentation GNU Sed, qui le fait) . La réponse ci-dessus fonctionne avec les deux implémentations; pour un aperçu de toutes les différences, voir ici .Sur mon mac, ce qui suit insère un seul 'n' au lieu d'une nouvelle ligne:
Cela remplace par une nouvelle ligne:
la source
sed -i '' -e ...
et j'avais des problèmes avec un^M
signe d'insertion M (ctrl + m) pour être écrit dans le fichier. J'ai fini par utiliser perl avec les mêmes paramètres.\n
).echo...
et la nouvelle ligne) que je viens de le faire dans vim.sed "s/regexp/`echo`/g"
- cela produira un seul LF au lieu de LF-CR`echo`
donnera la chaîne vide , car les substitutions de commandes coupent invariablement toutes les nouvelles lignes de fin. Il n'y a aucun moyen d'utiliser une substitution de commande pour insérer directement une seule nouvelle ligne (et l'insertion\n\r
- c'est-à-dire, un CR supplémentaire - est une idée terrible).la source
$'\n'
s'appuie sur le shell pour générer la nouvelle ligne. Ces solutions peuvent ne pas être portables. Celui-ci est. Bien sûr, c'est aussi une copie du deuxième exemple de la réponse de tgamblin de 2009.Dans ce cas, je n'utilise pas sed. J'utilise tr.
Cela prend la virgule et la remplace par le retour chariot.
la source
cat Somefile | tr ',' '\n'
YMMVVous pouvez utiliser des one-liners perl comme vous le faites avec sed, avec l'avantage du support complet des expressions régulières perl (qui est beaucoup plus puissant que ce que vous obtenez avec sed). Il y a aussi très peu de variation entre les plates-formes * nix - perl est généralement perl. Ainsi, vous pouvez arrêter de vous soucier de la façon dont la version de sed de votre système particulier fait ce que vous voulez.
Dans ce cas, vous pouvez faire
-pe
met perl dans une boucle "exécuter et imprimer", un peu comme le mode de fonctionnement normal de sed.'
cite tout le reste pour que le shell n'interfère pas()
entourant l'expression régulière est un opérateur de regroupement.$1
sur le côté droit de la substitution imprime tout ce qui correspond à l'intérieur de ces parenthèses.Enfin,
\n
est une nouvelle ligne.Que vous utilisiez ou non des parenthèses comme opérateur de regroupement, vous devez échapper toutes les parenthèses que vous essayez de faire correspondre. Ainsi, une expression régulière correspondant au modèle que vous avez énuméré ci-dessus serait quelque chose comme
\(
ou\)
correspond à un paren littéral et\d
correspond à un chiffre.Mieux:
J'imagine que vous pouvez comprendre ce que font les nombres entre accolades.
De plus, vous pouvez utiliser des délimiteurs autres que / pour votre regex. Donc, si vous avez besoin de correspondre / vous n'aurez pas besoin d'y échapper. L'un ou l'autre des éléments ci-dessous est équivalent à l'expression régulière au début de ma réponse. En théorie, vous pouvez remplacer n'importe quel caractère pour le standard /.
Quelques dernières réflexions.
utiliser
-ne
au lieu de-pe
agit de la même manière, mais ne s'imprime pas automatiquement à la fin. Cela peut être pratique si vous souhaitez imprimer vous-même. Par exemple, voici un grep-alike (m/foobar/
est une correspondance regex):Si vous trouvez que le traitement des nouvelles lignes est gênant et que vous voulez que cela soit géré par magie pour vous, ajoutez
-l
. Pas utile pour l'OP, qui travaillait avec des nouvelles lignes, cependant.Astuce bonus - si vous avez installé le paquet pcre, il est livré avec
pcregrep
, qui utilise des expressions régulières entièrement compatibles avec Perl.la source
Hmm, les nouvelles lignes juste échappées semblent fonctionner dans les versions plus récentes de
sed
(j'ai GNU sed 4.2.1),la source
a bien fonctionné sur El Captitan avec le
()
soutienla source
Pour insérer une nouvelle ligne dans le flux de sortie sous Linux, j'ai utilisé:
Où
file1
était:Avant le remplacement sur place du sed, et:
Après le remplacement sur place du sed. Veuillez noter l'utilisation de
\\\n
. Si les motifs ont un à l'"
intérieur, évitez d'utiliser\"
.la source
sed
insère\n
au lieu de LF car il obtient\\n
le paramètre du shell. --- Ce code fonctionne:sed -i "s/def/abc\ndef/" file1
. ---GNU sed version 4.2.1
,GNU bash, version 4.1.2(1) / 4.2.25(1)
(CentOS version 6.4 / Ubuntu 12.04.3).dans sed, vous pouvez référencer des groupes dans votre motif avec "\ 1", "\ 2", .... donc si le motif que vous recherchez est "PATTERN", et que vous voulez insérer "BEFORE" devant lui , vous pouvez utiliser, sans échapper
c'est à dire
la source
Vous pouvez également le faire avec awk, en utilisant
-v
pour fournir le modèle:Cela vérifie si une ligne contient un motif donné. Si tel est le cas, il ajoute une nouvelle ligne au début de celui-ci.
Voir un exemple de base:
Notez que cela affectera tous les modèles d'une ligne:
la source
1
est utilisé dans Awk comme un raccourci vers{print $0}
. La raison en est que toute condition évaluée à True déclenche l'action par défaut d'Awk, qui consiste à imprimer l'enregistrement en cours.Cela fonctionne sous MAC pour moi
Dono si c'est parfait ...
la source
Après avoir lu toutes les réponses à cette question, il m'a encore fallu de nombreuses tentatives pour obtenir la syntaxe correcte dans l'exemple de script suivant:
Le script ajoute une nouvelle ligne
\n
suivie d'une autre ligne de texte à la fin d'un fichier à l'aide d'une seulesed
commande.la source
\ 0 est la valeur nulle, donc votre expression est remplacée par une valeur nulle (rien), puis ...
\ n est la nouvelle ligne
Sur certaines versions d'Unix ne fonctionne pas, mais je pense que c'est la solution à votre problème.
la source
Dans vi sur Red Hat, j'ai pu insérer des retours chariot en utilisant uniquement le caractère \ r. Je crois que cela exécute en interne «ex» au lieu de «sed», mais c'est similaire, et vi peut être un autre moyen de faire des modifications en masse telles que des correctifs de code. Par exemple. J'entoure un terme de recherche avec une instruction if qui insiste sur les retours chariot après les accolades:
Notez que je lui ai également fait insérer des onglets pour que les choses s'alignent mieux.
la source