2017-03-19 2 views
0

Das folgende Problem sieht für mich komisch aus.Bash/Tcl: Wie werden zufällig generierte Namen in der gleichen Spalte in der Textdatei umbenannt?

Betrachten Sie die folgende Protokolldatei:

-------------------------------------------------- 
-----    INPUT DATA    ----- 
-------------------------------------------------- 
      NAME     Atribute1 Atribute2 
-------------------------------------------------- 
name        0   0 
name1        8   7 
name5        3   3 
name3        4   2 
name22        5   8 

... 
//Skipped ....       ...  

--------------------------------------------------- 
-----    INPUT DATA    ----- 
--------------------------------------------------- 
      NAME     Attribute1 Attribute2 
--------------------------------------------------- 
name10        0   0 
name1        8   7 
name3        0   0 
name22        0   0 
name33        9   0 
name45        0   0 
...             ... 
//Skipped .... 

Die Namen aus der ersten Spalte erzeugt werden, und tatsächlich Ich weiß nichts über sie.

Frage: Wie alle Namen aus der ersten Spalte umbenennen, so etwas zu bekommen:

-------------------------------------------------- 
-----    INPUT DATA    ----- 
-------------------------------------------------- 
      NAME     Atribute1 Atribute2 
-------------------------------------------------- 
x          0  0 
x1          8  7 
x2          3  3 
x3          4  2 
x4          5  8 

--------------------------------------------------- 
-----    INPUT DATA      ----- 
--------------------------------------------------- 
      NAME     Attribute1 Attribute2 
--------------------------------------------------- 
x5         0   0 
x1         8   7 
x3         0   0 
x6         0   0 
x7         9   0 
x8         0   0 
x9         0   0 
x10         0   0 

, dass die ersten Namen zu benennen ist mit x-es: „x1, x2 .... "

Einschränkung: Das gleiche x(i) sollte doppelten Namen zugewiesen werden. Wie im Beispiel: name1 und name3 existieren auch in der zweiten Tabelle, daher sind ihre neuen Namen in beiden Tabellen gleich (x1, x3).

Ich suche nach Lösung in bash oder tcl (bash ist mehr bevorzugt)

+0

Meinst du pure bash (d. H. Verwenden Sie den Read-Builtin und tun String-Verarbeitung innerhalb von Bash) oder nur mit Bash und Core-Dienstprogramme? ... Ich habe auch meine Antwort geschrieben, vorausgesetzt, dass Ihre Eingabe bereits in zwei Dateien aufgeteilt ist. Haben Sie eine riesige Protokolldatei mit einem Header, der manchmal wiederholt wird? –

Antwort

1

Eine Sache, die Sie ist awk in einem Shell-Skript verwenden, tun können, den Überblick über die die Zuordnung zwischen den ursprünglichen Namen zu halten und die neu generierte Namen. Dieses spezielle awk-Skript behandelt die erste Datei anders, indem NR und FNR integrierte Variablen verglichen werden, die die Gesamtzahl der verarbeiteten Datensätze bzw. die Anzahl der in der aktuellen Datei verarbeiteten Datensätze zählen. Weitere Informationen zu diesem Trick hier: https://unix.stackexchange.com/questions/106645/processing-two-files-using-awk

Grundsätzlich hält dieses Programm Spur eines Zählers c und einen Wörterbuch name, die die ursprünglichen Namen auf den neuen Karten (die nur c mit einem Präfix von "x" ist).

Es gibt auch zwei Arten von Linien. Kopfzeilen beginnen mit "-" oder " ", diese werden ignoriert und gedruckt wie sie sind.

Eine Sache, die Sie möglicherweise tun müssen, ist die Datei danach aufzuteilen, es sei denn, die Dateien sollen verkettet werden.

#!/bin/sh 
awk ' 
    BEGIN { c = 0; } 

    /^[- ]/ { 
     print; 
    } 

    /^[^- ]/ && NR == FNR { 
     new_name = "x" c; 
     name[$1] = new_name; 
     c += 1; 
     $1 = new_name; 
     print; 
    } 

    /^[^- ]/ && NR != FNR { 
     if ($1 in name) { 
      $1 = name[$1]; 
     } else { 
      new_name = "x" c; 
      c += 1; 
      $1 = new_name; 
     } 
     print; 
    } 

' input.txt input2.txt 

Beachten Sie, dass dieses Programm keine Formatierung der Fall ist, awk hat eine printf Funktion, die Formatdaten mit einer festen Anzahl von Spalten verwendet werden können.

1

Tcl: Verwenden Sie ein Wörterbuch. Wenn der Name bereits existiert. Wenn nicht, füge es dem Wörterbuch hinzu. Geben Sie auf jeden Fall den Ersatznamen aus.

namespace eval names { 
namespace export lookup 
    variable names 
    set names {} 
    proc lookup name { 
     variable names 
     if {![dict exists $names $name]} { 
      dict set names $name [dict size $names] 
     } 
     return x[dict get $names $name] 
    } 
} 

Dokumentation:

set names {} 
proc lookup name { 
    global names 
    if {![dict exists $names $name]} { 
     dict set names $name [dict size $names] 
    } 
    return x[dict get $names $name] 
} 

Wenn Globals Sie stören, können Sie sie in einem Namensraum verbergen kann ! (operator), dict, global, if, namespace, proc, return, set, variable

Verwandte Themen