Imprimir columnas con un patrón específico y todos los valores

Imprimir columnas con un patrón específico y todos los valores

Tengo un archivo como este:

     OV2  OVI  1VI  OV3  3VI  
er    23   23   23   23   23  
tr    24   24   24   24   24

Quiero imprimir la primera columna junto con las columnas cuyo nombre contenga VI(no sé qué columnas contendrán la cadena de antemano). En el ejemplo anterior, el resultado debería ser así:

     OVI  1VI  3VI  
er    23   23   23     
tr    24   24   24  

todas las columnas deben estar delimitadas por tabulaciones.

Respuesta1

perl -lane '$,="\t";
   $. == 1 and @A = grep $F[$_] =~ /VI/, 0..$#F;
   print @F[0,@A];
' yourfile

Resultados

ID      OVI     1VI     3VI
er      23      23      23
tr      24      24      24

Laboral

  • Desde la primera línea, $. == 1extrae los índices de los campos que contienen la cadena VI.
  • Armados con esta lista de índices ahora en matriz @A, simplemente seguimos adelante y cortamos el primer campo + los campos enumerados en la @Amatriz de la @Fmatriz. Se OFS=$,ha establecido en TAB. YMMV.

awk

awk -v OFS="\t" '
   NR==1{
      for ( i=2; i<=NF; i++ )
         if ( $i ~ /VI/ )
            str = str OFS i
      N = split(str, A, OFS)
   }{
      s = $1
      for ( i=2; i<=N; i++ )
         s = s OFS $(A[i])
      $0 = s
   }1
' yourfile

SED

sed -e '
   # TAB->spc, multiple spc -> single spc, trim leading/trailing spc
   y/ / /;s/[ ]\{2,\}/ /g;s/^[ ][ ]*//;s/[ ][ ]*$//

   # only for first line, remove the first field and store remaining in hold area
   1{
      h
         s/[ ]/\
/
         s/.*\n//
      x
   }

   # append hold area (which now has 2nd...last fields
   # data of the first record) to the present line and
   # place a marker at the end of the first field
   G
   s/[^ ][^ ]*[ ]/&\
/

   # setup a do-while loop which progressively either keeps VI data or trims it
   :loop
      #  1     2                      3
      s/\(\n\)\([^ ][^ ]*\)[ ]\{0,1\}\(.*\n\)[^ ]*VI[^ ]*[ ]\{0,1\}/ \2\1\3/;tloop
      s/\(\n\)[^ ][^ ]*[ ]\{0,1\}\(.*\n\)[^ ][^ ]*[ ]\{0,1\}/\1\2/
   /\n\n$/!bloop
   # loop ends when the two \ns collide at the end of line

   # remove the two \ns and what remains is what you wanted
   s///

' yourfile

Respuesta2

awksolución:

awk 'BEGIN{FS="[\t ]+"; OFS="\t"}NR==1{for(i=2;i<=NF;i++)
    {if($i~/VI/) a[i]; }}{r=$1; for(i in a) r=r OFS $i; print l}' file

La salida:

    OVI 1VI 3VI
er  23  23  23
tr  24  24  24

  • FS="[\t ]+"- separador de campo de entrada

  • OFS="\t"- separador de campo de salida

  • NR==1- Por el primeroencabezamientolínea

  • if($i~/VI/) a[i]- capturar el número de campo si coincideVI

  • r=$1; for(i in a) r=r OFS $i; print r- iterar a través de los números de campo necesarios e imprimir sus valores respectivos


Si encuentra una ruptura de orden, utilice la siguiente asorti()función (para ordenar la matriz por índices):

awk 'BEGIN{FS="[\t ]+"; OFS="\t"}NR==1{for(i=2;i<=NF;i++)
    {if($i~/VI/) a[i]; }}{r=$1; asorti(a,b); for(i in b) {r=r OFS $(b[i])} print r}' file

Respuesta3

Solución de secuencia de comandos Python. Opera basándose en el análisis de la primera línea y la creación de una lista de columnas. Aquellas columnas que no tienen VI se establecen en Ninguna. Todas las demás líneas se dividen en palabras y se unen en pares con elementos de la lista de columnas para comparar. Si el elemento de la columna correspondiente es Ninguno, esa palabra de la línea actual no se imprimirá. De lo contrario, se imprimen los elementos que no son Ninguno.

#!/usr/bin/env python3
import sys

with open(sys.argv[1]) as fd:
    indexes = []
    for index,line in enumerate(fd):
        if index == 0:
            columns = line.strip().split()
            for i,col in enumerate(columns):
                if 'VI' in col or i == 0:
                    indexes.append(col)
                else:
                    indexes.append(None)
            for x in indexes:
                if x:
                    print(x,end=" ")
            print("")
            continue
        for j in zip(line.strip().split(),indexes):
            if j[1]:
                print(j[0],end=" ")
        print("")

Nota: reemplace end=" "con end="\t"para tener una salida delimitada por tabulaciones

Prueba de funcionamiento:

$ ./get_colums.py input.txt                                                                                              
ID  OVI 1VI 3VI 
er  23  23  23  
tr  24  24  24  

información relacionada