Drucken von Spalten mit einem bestimmten Muster und allen Werten

Drucken von Spalten mit einem bestimmten Muster und allen Werten

Ich habe eine Datei wie diese:

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

Ich möchte die 1. Spalte zusammen mit allen Spalten drucken, deren Name enthält VI(ich weiß vorher nicht, welche Spalten die Zeichenfolge enthalten werden). Im obigen Beispiel sollte die Ausgabe folgendermaßen aussehen:

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

Alle Spalten sollten durch Tabulatoren getrennt sein.

Antwort1

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

Ergebnisse

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

Arbeiten

  • Extrahieren Sie aus der ersten Zeile $. == 1die Indizes der Felder, die die Zeichenfolge enthalten VI.
  • Ausgestattet mit dieser Liste von Indizes, die sich jetzt im Array befinden @A, schneiden wir einfach das 1. Feld + die im @AArray aufgelisteten Felder aus dem @FArray heraus. Das OFS=$,wurde auf ein gesetzt 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

Antwort2

awkLösung:

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

Die Ausgabe:

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

  • FS="[\t ]+"- Eingabefeldtrennzeichen

  • OFS="\t"- Ausgabefeldtrennzeichen

  • NR==1- zum ersten MalHeaderLinie

  • if($i~/VI/) a[i]- Erfassen der Feldnummer, wenn diese übereinstimmtVI

  • r=$1; for(i in a) r=r OFS $i; print r- Durchlaufen der benötigten Feldnummern und Drucken der entsprechenden Werte


Wenn Sie auf eine Unterbrechung der Reihenfolge stoßen, verwenden Sie die folgende asorti()Funktion (um das Array nach Indizes zu sortieren):

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

Antwort3

Python-Skriptlösung. Funktioniert auf der Grundlage der Analyse der ersten Zeile und dem Aufbau einer Spaltenliste. Die Spalten, die kein VI enthalten, werden auf „None“ gesetzt. Alle anderen Zeilen werden in Wörter aufgeteilt und zum Vergleich mit Spaltenlistenelementen paarweise verbunden. Wenn das entsprechende Spaltenelement „None“ ist, wird das Wort aus der aktuellen Zeile nicht gedruckt. Andernfalls werden Dinge gedruckt, die nicht „None“ sind.

#!/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("")

Hinweis: Ersetzen Sie end=" "durch end="\t", um eine tabulatorgetrennte Ausgabe zu erhalten

Testlauf:

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

verwandte Informationen