Elimine uno o más campos, delimitados por un "-", al final de la línea

8

Voy a analizar los datos 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

Espero el resultado como estos a continuación

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

Estoy pensando que tengo que cambiar -para ser un espacio y luego ejecutar este comando

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

Obtuve eso de este https://stackoverflow.com/a/27794421/8162936 Después de analizarlo, cambiaré el espacio para que sea una exageración -.

¿Alguien sabe la mejor práctica o el comando de shell de una línea para analizarlo? Gracias a todos

Nicky Puff
fuente

Respuestas:

10

con sedusted puede hacer:

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

haga coincidir un patrón -anythingdos veces (...){2}desde el final $de cada línea y elimínelo.

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

Esto se usa sedpara hacer coincidir las dos últimas subcadenas delimitadas por guiones en cada línea y eliminarlas. [[:alnum:]]coincidirá con cualquier carácter alfanumérico.

Puedes acortarlo a

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

es decir, unir y eliminar dos conjuntos de -[[:alnum:]]*ath al final de cada línea.

Con GNU awk, también podrías hacer

$ 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

pero cambiar de NFesta manera no es portátil y debe evitarse (no hay garantía de que cambie el registro actual). No funcionaría con BSD awk, por ejemplo.

Con el estándar awk, sin recurrir al uso sub()(que sería simplemente imitar sed), tendría que recrear el registro actual de los campos que desea usar (en nuestro caso, todos menos los dos últimos campos delimitados por guiones):

$ 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
fuente
4

Con revy cut:

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

Invierta las líneas, cutcampo 3 hasta el final de la línea e invierta el texto nuevamente.


Con grep(y PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -Puse expresiones regulares compatibles con perl con un lookahead positivo que (?...)contenga dos coincidencias -seguidas de cualquier no -carácter
  • -o imprimir solo partes coincidentes
Freddy
fuente
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

Esto divide automáticamente cada línea de entrada en una matriz @F, utilizando delimitador -.

Luego imprime una porción de matriz de todos menos los dos últimos campos, reunidos con -caracteres.

cas
fuente
1

puedes hacerlo de varias maneras como se muestra aquí:

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

Divida las líneas en un guión, configure la unión de elementos de la matriz en guión, recorte los dos últimos elementos y configure la línea actual en la matriz unida con guiones.

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

Esto es con el procesamiento de cadena simple:

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

.

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

Resultados:

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