Rimuovere uno o più campi, delimitati da un "-", alla fine della riga


8

Analizzerò i dati 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

Mi aspetto il risultato come questi qui sotto

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

Sto pensando che devo cambiare -per essere uno spazio e quindi eseguire questo comando

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

L'ho preso da questo https://stackoverflow.com/a/27794421/8162936 Dopo aver analizzato, cambierò lo spazio per tornare -indietro.

Qualcuno conosce la best practice o il comando shell one-liner per analizzarlo? Ringrazia tutti

Risposte:


10

con sedte puoi fare:

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

abbina un motivo come -anythingdue volte (...){2}dalla fine $di ogni riga e rimuovilo.


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

Questo utilizza sedper abbinare le ultime due sottostringhe delimitate da trattino su ciascuna riga e rimuoverle. [[:alnum:]]corrisponderà a qualsiasi carattere alfanumerico.

Puoi accorciarlo a

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

cioè, abbina ed elimina due serie di -[[:alnum:]]*ath alla fine di ogni riga.

Con GNU awk, potresti anche farlo

$ 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

ma cambiare in NFquesto modo non è portatile e dovrebbe essere evitato (non vi è alcuna garanzia che cambi il record corrente). Non funzionerebbe con BSD awk, per esempio.

Con lo standard awk, senza ricorrere all'utilizzo sub()(che sarebbe solo imitare sed), dovresti ricreare il record corrente dai campi che vorresti usare (nel nostro caso, tutti tranne gli ultimi due campi delimitati da trattino):

$ 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

4

Con reve cut:

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

Invertire le linee, cutcampo 3 fino alla fine della riga e invertire nuovamente il testo.


Con grep(e PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -Pusa espressioni regolari compatibili con perl con un lookahead positivo (?...)contenente due corrispondenze -seguite da non -caratteri
  • -o stampa solo parti abbinate

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

In questo modo, ogni riga di input viene automaticamente suddivisa in array @F, usando il delimitatore -.

Quindi stampa una porzione di matrice di tutti tranne gli ultimi due campi, ricongiunti con i -caratteri.


1

puoi farlo in vari modi come mostrato qui:

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

Dividi le linee su un trattino, imposta il joiner dell'elemento dell'array su trattino, ritaglia gli ultimi due elementi e imposta la linea corrente sull'array unita con i trattini.

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

Questo è con l'elaborazione di stringhe semplici:

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

.

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

risultati:

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.