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
oldtextcontient des métacaractères de regexp etnewtextcontient des références arrière. Par exemple, essayez-les quandoldtextvautacet que le fichier d'entrée contient à la foisacetabc, et quandnewtextvautd&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?