web-dev-qa-db-fra.com

sed: remplace une partie de la ligne

Comment remplacer une partie d'une ligne par sed?

La ligne 

DBSERVERNAME     xxx

devrait être remplacé pour:

DBSERVERNAME     yyy

La valeur xxx peut varier et il y a deux onglets entre nom_serveur et la valeur. Cette paire nom-valeur est l'une des nombreuses d'un fichier de configuration.

J'ai essayé avec le backreference suivant:

echo "DBSERVERNAME    xxx" | sed -rne 's/\(dbservername\)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'

et cela a entraîné une erreur: référence non valide\1 sur le RHS de la commande `s '.

Quel est le problème avec l'expression? Utiliser GNU sed.

34
calvinkrishy

Cela marche:

sed -rne 's/(dbservername)\s+\w+/\1 yyy/gip'

(Lorsque vous utilisez l'option -r, vous n'êtes pas obligé d'échapper aux parenthèses.)

Peu d'explication:

  • -r est une expression régulière étendue - fait une différence dans la façon dont l'expression régulière est écrite.
  • -n n'imprime que si spécifié - sed imprime par défaut sinon,
  • -e signifie que ce qui suit est une expression. Décomposons l'expression:
    • s/// est la commande pour search-replace, et ce qui se trouve entre la première paire est la regex à comparer, et la seconde paire, le remplacement,
    • gip, qui suit la commande search replace; g signifie global, c’est-à-dire que chaque match au lieu du premier sera remplacé dans une ligne; i est insensible à la casse; p signifie imprimer lorsque vous avez terminé (rappelez-vous du drapeau -n de plus tôt!),
    • Les crochets représentent une partie du match, qui sera posée plus tard. Donc dbservername est la première partie du match,
    • \s est un espace, + signifie une ou plusieurs occurrences (vs *, zéro ou plus),
    • \w est un mot, c'est-à-dire une lettre, un chiffre ou un trait de soulignement,
    • \1 est une expression spéciale pour GNU sed qui affiche la première correspondance entre crochets dans la recherche associée.
42
Jeremy Stein

D'autres ont déjà mentionné l'échappement de parenthèses, mais pourquoi avez-vous besoin d'une référence arrière, si la première partie de la ligne est constante? 

Vous pourriez simplement faire 

sed -e 's/dbservername.*$/dbservername yyy/g'
8
Vicky

Vous échappez à votre (et). Je suis sûr que tu n'as pas besoin de faire ça. Essayer:

 sed -rne's/(dbservername) [[: blank:]] +\([[: alpha:]] + \)/\ 1 yyy/gip '
2
apandit

Vous ne devriez pas échapper aux choses lorsque vous utilisez des guillemets simples. c'est à dire.

echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername[[:blank:]]+)([[:alpha:]]+)/\1 yyy/gip'
1
Matthew Scharley

Tu ne devrais pas échapper à tes parents. Essayer:

echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername)[[:blank:]]+([[:alpha:]]+)/\1 yyy/gip'
1
Pesto

Cela pourrait fonctionner pour vous:

echo "DBSERVERNAME     xxx" | sed 's/\S*$/yyy/'
DBSERVERNAME     yyy
1
potong