Je cherche à remplacer des lignes dans un fichier. c'est-à-dire que si "oldtext" est dans le fichier au début d'une ligne, remplacez la ligne entière par "newtext".
Le début de la ligne peut être ^oldtext
ou oldtext
sera indenté par des espaces / tabulations
sed -i -e 's/^$prefixspaces$newtext*$/$prefixspaces$newtext/g' myfile.txt
J'ai besoin de calculer le même niveau d'indentation que "oldtext"
prefixspaces = <number of spaces before the "mytext", converting tabs to 4 spaces>
Je me rends compte que sed est peut-être le meilleur moyen d'y parvenir, mais je dois d'abord calculer l'espace de préfixe, puis ma sortie est quelque chose comme:
grep "^[\S]oldtext" myfile.txt # doesn't work
Je ne sais pas comment calculer cela. Peut-être que $prefixspace
peut être $prefixspace
dans un groupe ()
ou quelque chose pour que sed puisse facilement le calculer et travailler avec? C'est peut-être un one-liner sed ou awk, mais je ne peux pas le résoudre après quelques recherches.
3 Réponses :
Comme ça:
\1 the 0 or more spaces from group1 newtext 'newtext'
Explication:
chercher
^ beginning of the line \( *\) capture 0 or more spaces in group 1 oldtext 'oldtext' .* rest of the line
remplacer
sed 's/^\( *\)oldtext.*/\1newtext/' file
sed
Une autre façon de faire, en plus de la réponse acceptée, consiste à utiliser des caractères de classe ([[: space:]]) et des expressions régulières d'extension avec le paramètre -r
:
newtext newtext newtext newtext
Et le résultat sera:
$ perl -lpe 's/^(\s*)oldtext.*/\1newtext/' << _eof oldtext this oldtext this oldtext this oldtext also this _eof
Dans ([[:space:]]*)
, nous avons capturé un groupe avec zéro ou plusieurs espaces, mais nous pouvons spécifier un certain nombre.
awk
Nous pouvons utiliser gsub
pour remplacer les espaces et compter les temps:
newtext newtext newtext newtext
Et le résultat sera:
$ awk \ -v old="oldtext" \ -v new="newtext" \ 'BEGIN{re="^[[:space:]]*"old} { if (match($0,re)) { i=gsub(/ /,"") while (--i) printf " " print new } else print }' << _eof oldtext this oldtext also this oldtext and this oldtext also this _eof
perl
Nous pouvons y parvenir avec l'utilisation de perl
dans un style de type sed :
newtext a newtext
Et le résultat sera:
$ sed -r 's/^([[:space:]]*)oldtext.*/\1newtext/' << _eof oldtext this a oldtext also this _eof
Cela pourrait fonctionner pour vous (GNU sed):
sed '/^\s*oldtext/s/\S.*/newtext/' file
Correspond à l' oldtext
au début d'une ligne ou en retrait et remplacez-le à partir du premier caractère d'espacement non blanc.
Pourriez-vous s'il vous plaît publier un échantillon de l'entrée et de la sortie attendue dans votre question pour le rendre plus clair.
s/^\([[:space:]]*\)oldtext/\1$newtext/
?C'est génial @Shawn, j'ai ajouté
.*
Après oldtext pour qu'il remplace toute la ligne et qu'il veuille n'importe quel espace, alors il l'a changé en\s*
au début de la ligne. Fonctionne bien.Vous devriez tester les réponses que vous avez obtenues lorsque
oldtext
contient des métacaractères de regexp etnewtext
contient des références arrière. Par exemple, essayez-les quandoldtext
vautac
et que le fichier d'entrée contient à la foisac
etabc
, et quandnewtext
vautd&e
. Vous devriez faire des correspondances de chaînes littérales et des remplacements de chaînes littérales, pas des correspondances d'expression régulière et des remplacements de chaînes activés par les références rétrospectives, qui sont tout ce que sed prend en charge et jusqu'à présent toutes les réponses le font.ok, avez-vous un moyen de résoudre ce problème Ed?