Supprimer un ou plusieurs champs, délimités par un «-», en fin de ligne

8

Je vais analyser les données googleapis.txt

bucket,abc-def-ghi-45gjd4-wwxis
bucket,dde-wwq-ooi-66ciow-po22q
instance,jkl-mno-1-zzz-68dkakw-oo9w8
disk,pqr-stu-10-kuy-l2oxapw-rp4lt

J'attends le résultat comme ci-dessous

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Je pense que je dois changer -pour être un espace , puis exécuter cette commande

cat googleapis.txt | awk '{$NF="";sub(/[ \t]+$/,"")}1' | awk '{$NF="";sub(/[ \t]+$/,"")}1'

Je l'ai obtenu de ce https://stackoverflow.com/a/27794421/8162936 Après l'analyse, je changerai l'espace pour être un hypen -.

Quelqu'un connaît-il la meilleure pratique ou la commande shell à une ligne pour l'analyser? Merci a tous

Nicky Puff
la source

Réponses:

10

avec sedvous pouvez faire:

sed -E 's/(-[^-]*){2}$//' infile

faites correspondre un motif comme -anythingdeux fois à (...){2}partir de la fin $de chaque ligne et supprimez-le.

αғsнιη
la source
7
$ sed 's/-[[:alnum:]]*-[[:alnum:]]*$//' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Cela permet de sedfaire correspondre les deux dernières sous-chaînes délimitées par des tirets sur chaque ligne et de les supprimer. [[:alnum:]]correspondra à n'importe quel caractère alphanumérique.

Vous pouvez le raccourcir à

sed 's/\(-[[:alnum:]]*\)\{2\}$//' file

c'est-à-dire, faire correspondre et supprimer deux ensembles de -[[:alnum:]]*la fin de chaque ligne.

Avec GNU awk, vous pourriez aussi faire

$ awk -F '-' 'BEGIN { OFS=FS } { NF -= 2; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

mais une NFtelle modification n'est pas portable et doit être évitée (il n'y a aucune garantie qu'elle modifie l'enregistrement actuel). Cela ne fonctionnerait pas avec BSD awk, par exemple.

Avec la norme awk, sans recourir à l'utilisation sub()(qui ne serait que pour imiter sed), vous devrez recréer l'enregistrement en cours à partir des champs que vous souhaitez utiliser (dans notre cas, tous sauf les deux derniers champs délimités par des tirets):

$ awk -F '-' 'BEGIN { OFS=FS } { nf = split($0,a) - 2; $0=""; for (i=1; i<=nf; ++i) $i = a[i]; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy
Kusalananda
la source
4

Avec revet cut:

rev file | cut -d'-' -f3- | rev

Inversez les lignes, cutchamp 3 jusqu'à la fin de la ligne et inversez le texte à nouveau.


Avec grep(et PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -Putiliser des expressions régulières compatibles perl avec une anticipation positive (?...)contenant deux correspondances -suivies de tous les -caractères non
  • -o imprimer uniquement les pièces assorties
Freddy
la source
4
$ perl -F- -lane 'print join "-", @F[0..($#F-2)]' googleapis.txt
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Cela fractionne automatiquement chaque ligne d'entrée dans un tableau à l' @Faide d'un délimiteur -.

Il imprime ensuite une tranche de tableau de tous les champs sauf les deux derniers, rejoints par des -caractères.

cas
la source
1

vous pouvez le faire de différentes manières, comme indiqué ici:

$ perl -F- -pale '$"="-";$#F-=2;$_="@F"' file

Fractionnez les lignes sur un tiret, définissez la jonction d'éléments de tableau sur tiret, coupez les deux derniers éléments et définissez la ligne actuelle sur tableau joint avec des tirets.

$ awk -F- '{
   t = $1
   for ( i=2; i<NF-1; i++ ) t = t FS $i
   $0 = t
}1' file

C'est avec le traitement de chaîne simple:

$ perl -lne 'print substr($_, 0, rindex($_,"-",-1+rindex($_,"-")))' file

.

$ sed -ne '
   y/-/\n/
   :a;h;s/\n/-/;/\n.*\n/ba
   g;P
' file

Résultats:

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy
Rakesh Sharma
la source