J'ai un fichier qui a un tas de noms d'hôtes corrélés avec des IP qui ressemble à ceci:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Je veux que ça ressemble à ceci:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
Comment puis-je remplacer le. (points) de la première colonne avec - (trait d'union) afin de faciliter un tri par la deuxième colonne? Je pensais utiliser sed pour remplacer les points jusqu'au premier espace, ou remplacer chaque point sauf les trois derniers, mais j'ai du mal à comprendre regex et sed. Je peux effectuer des remplacements simples mais c'est bien au-dessus de ma tête!
Cela fait partie d'un script plus large que j'ai écrit en bash. Je suis coincé dans cette partie.
awk
est basée surnawk
, donc toutes lesawk
implémentations modernes devraient avoirgsub
. Sous Solaris, vous pouvez avoir besoin de/usr/xpg4/bin/awk
ounawk
.Si vous devez effectuer les substitutions sur le premier champ, le mieux est d'utiliser la solution awk de Rahul mais attention, cela peut affecter l'espacement (les champs sont réécrits avec un seul espace entre eux).
Vous pouvez l'éviter en l'écrivant à la place:
Le
-p
drapeau signifie "lire le fichier d'entrée ligne par ligne et imprimer chaque ligne après avoir appliqué le script donné par-e
". Ensuite, remplacez (s|pattern|replacement|
) la première séquence de caractères non-espace (\S+
) par le motif correspondant ($&
) après avoir remplacé tous.
par-
. L'astuce consiste à utilisers|||e
où l'e
opérateur évaluera une expression comme remplacement. Ainsi, vous pouvez avoir un remplacement (tr/./-/
) appliqué à la correspondance ($&
) de la précédente (s|||e
).Si vous devez remplacer chaque
.
par un-
sauf les 3 derniers, par GNUsed
et en supposant que vous avez unerev
commande:la source
/r
fonctionne).Sed n'est pas l'outil le plus simple pour le travail - voir d'autres réponses pour de meilleurs outils - mais cela peut être fait.
Pour remplacer
.
par-
seulement au premier espace, l' utilisations
dans une boucle.(Notez que certaines implémentations sed ne prennent pas en charge les commentaires sur la même ligne. GNU sed le fait.)
Pour effectuer à la place le remplacement jusqu'au dernier espace:
Une autre technique utilise l'espace de retenue de sed. Enregistrez le bit que vous ne souhaitez pas modifier dans l'espace d'attente, effectuez votre travail, puis rappelez l'espace d'attente. Ici, je divise la ligne au dernier espace et remplace les points par des tirets dans la première partie.
la source
Depuis que Rahul vous a donné la réponse canonique pour votre cas d'utilisation, j'ai pensé essayer de répondre au problème titulaire: remplacer toutes les occurrences x, sauf les dernières x, d'une expression régulière:
Le code ci-dessus (testé) ne suppose pas que vous avez des champs séparés par des espaces. Il remplacera tous les points d'une ligne par des tirets à l'exception des 3 derniers points. Remplacez le
3
dans le code à votre convenance.la source
Vous pouvez utiliser de nombreux outils différents pour cela. Rahul Patil vous en a déjà donné
gawk
un alors voici quelques autres:perl
Le
-a
commutateur fait que perl divise automatiquement les lignes d'entrée sur les espaces et enregistre les champs résultants dans le tableau@F
. Le premier champ sera donc$F[0]
ainsi nous remplaçons (s///
) toutes les occurrences de.
avec-
dans le premier champ, puis imprimons le tableau entier.coquille
Ici, la boucle while lit le fichier et se divise automatiquement en espace blanc, ce qui crée deux champs,
$first
et$rest
. La construction${first//pattern/replacement}
remplace toutes les occurrences depattern
avecreplacement
.la source
perlrun(1)
je vais vous dire que-a
c'est du "mode autosplit", je préfère le considérer comme "awk
mode": DJe crois que c'est un peu plus facile à lire qu'un gros regex méchant. Fondamentalement, je viens de diviser la ligne en deux champs à l'espace blanc et d'utiliser sed sur la première partie.
Selon votre shell, vous pouvez également utiliser $ {host //./-} au lieu de la commande sed.
la source
Sans utiliser
g
à la fin de la commande, vous pouvez le faire… Cela remplacera simplement la 1ère occurrence du motifla source