Pas comment insérer une nouvelle ligne avant une ligne. Ceci demande comment insérer une nouvelle ligne avant un motif dans une ligne.
Par exemple,
sed 's/regexp/&\n/g'
insérera une nouvelle ligne derrière le motif regexp.
Comment puis-je faire la même chose mais devant le motif?
Voici un exemple de fichier d'entrée
somevariable (012)345-6789
Devraient devenir
somevariable
(012)345-6789
Certaines des autres réponses n'ont pas fonctionné pour ma version de sed. Changer la position de &
et \n
a fonctionné.
sed 's/regexp/\n&/g'
Edit: Cela ne semble pas fonctionner sous OS X, à moins d’installer gnu-sed
.
Cela fonctionne dans bash
, testé sous Linux et OS X:
sed 's/regexp/\'$'\n/g'
En général, pour $
suivi d'un littéral de chaîne entre guillemets simples bash
effectue une substitution de barre oblique inverse de style C, par ex. $'\t'
est traduit en onglet littéral. De plus, sed souhaite que votre littéral newline soit échappé avec une barre oblique inverse, d’où le \
avant $
. Enfin, le signe dollar lui-même ne doit pas être cité de manière à être interprété par Shell. Par conséquent, nous fermons la citation avant le $
, puis nous l'ouvrons à nouveau.
Edit: Comme suggéré dans les commentaires de @ mklement0, cela fonctionne aussi bien:
sed $'s/regexp/\\\n/g'
Ce qui se passe ici est que: l'intégralité de la commande sed est maintenant une chaîne de style C. Cela signifie que la barre oblique inverse que sed nécessite d'ê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 pourrez pas effectuer de substitutions de chaînes dans Shell (sans les rendre à nouveau laides).
Dans sed, vous ne pouvez pas ajouter facilement de nouvelles lignes dans le flux de sortie. Vous devez utiliser une ligne de continuation, ce qui est gênant, mais cela fonctionne:
$ sed 's/regexp/\
&/'
Exemple:
$ echo foo | sed 's/.*/\
&/'
foo
Voir ici pour plus de détails. Si vous voulez quelque chose de légèrement moins gênant, vous pouvez utiliser Perl -pe
avec des groupes de correspondance au lieu de sed:
$ echo foo | Perl -pe 's/(.*)/\n$1/'
foo
$1
fait référence au premier groupe correspondant dans l'expression régulière, les groupes étant entre parenthèses.
Sur mon mac, ce qui suit insère un seul 'n' au lieu de newline:
sed 's/regexp/\n&/g'
Ceci remplace par newline:
sed "s/regexp/\\`echo -e '\n\r'`/g"
echo one,two,three | sed 's/,/\
/g'
Dans ce cas, je n'utilise pas sed. J'utilise tr.
cat Somefile |tr ',' '\012'
Cela prend la virgule et la remplace par le retour chariot.
Vous pouvez utiliser Perl one-liners un peu comme vous le faites avec sed, avec l'avantage du support complet expression régulière Perl (beaucoup plus puissant que ce que vous obtenez avec sed). Il y a également très peu de variation entre les plates-formes * nix - Perl est généralement Perl. Vous pouvez donc cesser de vous demander comment faire en sorte que la version de sed de votre système fasse ce que vous voulez.
Dans ce cas, vous pouvez faire
Perl -pe 's/(regex)/\n$1/'
-pe
place 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 la regex est un opérateur de regroupement. $1
sur le côté droit de la substitution affiche ce qui a été mis en correspondance dans ces parenthèses.
Enfin, \n
est une nouvelle ligne.
Que vous utilisiez ou non des parenthèses en tant qu'opérateur de regroupement, vous devez échapper à toutes les parenthèses que vous essayez de faire correspondre. Donc, une expression rationnelle correspondant au motif que vous avez énuméré ci-dessus serait quelque chose comme:
\(\d\d\d\)\d\d\d-\d\d\d\d
\(
ou \)
correspond à un nom littéral, et \d
correspond à un chiffre.
Mieux:
\(\d{3}\)\d{3}-\d{4}
J'imagine que vous pouvez comprendre ce que font les chiffres entre accolades.
En outre, vous pouvez utiliser des délimiteurs autres que/pour votre expression rationnelle. Donc, si vous avez besoin d'égaler/vous n'aurez pas besoin d'y échapper. L'un des éléments ci-dessous est équivalent à l'expression régulière au début de ma réponse. En théorie, vous pouvez substituer n'importe quel caractère aux/à la norme.
Perl -pe 's#(regex)#\n$1#'
Perl -pe 's{(regex)}{\n$1}'
Conseil en prime - si le paquet pcre est installé, il est livré avec pcregrep
, qui utilise des expressions rationnelles compatibles Perl.
Hmm, les nouvelles lignes juste échappées semblent fonctionner dans les versions plus récentes de sed
(j'ai GNU sed 4.2.1),
dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'
a bien fonctionné sur El Capitan avec le support ()
Pour insérer une nouvelle ligne dans le flux de sortie sous Linux, j'ai utilisé:
sed -i "s/def/abc\\\ndef/" file1
Où file1
était:
def
Avant le remplacement en place de sed, et:
abc
def
Après le remplacement sur place de sed. Veuillez noter l'utilisation de \\\n
. Si les motifs contiennent un "
, quittez-le avec \"
.
Vous pouvez également le faire avec awk, en utilisant -v
pour fournir le motif:
awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
Ceci vérifie si une ligne contient un motif donné. Si c'est le cas, il ajoute une nouvelle ligne au début de celle-ci.
Voir un exemple de base:
$ cat file
hello
this is some pattern and we are going ahead
bye!
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
hello
this is some
pattern and we are going ahead
bye!
Notez que cela affectera tous les motifs d'une ligne:
$ cat file
this pattern is some pattern and we are going ahead
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d
this
pattern is some
pattern and we are going ahead
Après avoir lu toutes les réponses à cette question, il m'a fallu plusieurs tentatives pour obtenir la syntaxe correcte dans l'exemple de script suivant:
#!/bin/bash
# script: add_domain
# using fixed values instead of command line parameters $1, $2
# to show typical variable values in this example
ipaddr="127.0.0.1"
domain="example.com"
# no need to escape $ipaddr and $domain values if we use separate quotes.
Sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts
Le script ajoute une nouvelle ligne \n
suivie d'une autre ligne de texte à la fin d'un fichier à l'aide d'une seule commande sed
.
sed -e 's/regexp/\0\n/g'
\ est la valeur null, votre expression est donc remplacée par la valeur null (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.
echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow
dans sed, vous pouvez référencer des groupes dans votre modèle avec "\ 1", "\ 2", .... Ainsi, si le modèle que vous recherchez est "PATTERN", et que vous souhaitez insérer "BEFORE" devant celui-ci , vous pouvez utiliser, sans échapper
sed 's/(PATTERN)/BEFORE\1/g'
c'est à dire.
sed 's/\(PATTERN\)/BEFORE\1/g'
Dans vi sur Red Hat, j'ai pu insérer des retours à la ligne en utilisant uniquement le caractère\r. Je pense que cela exécute en interne "ex" au lieu de "sed", mais c'est similaire, et vi peut être un autre moyen d'effectuer des éditions en bloc telles que des correctifs de code. Par exemple. J'entends un terme de recherche avec une instruction if qui insiste sur le fait que les retours de chariot après les accolades sont les suivants:
:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/
Notez que je l'ai également fait insérer des onglets pour que les choses s'alignent mieux.
Cela fonctionne dans MAC pour moi
sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt
Dono si c'est parfait ...