El siguiente problema me parece raro.

Considere el siguiente archivo de registro:

--------------------------------------------------
-----                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 ....

Los nombres de la primera columna se generan y en realidad no sé nada sobre ellos .

Pregunta: Cómo cambiar el nombre de todos los nombres de la primera columna para obtener algo como esto:

--------------------------------------------------
-----                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

Es decir, renombrar los nombres iniciales con x-es: "x1, x2 ..."

Restricción: la misma x(i) debe asignarse a nombres duplicados. Como en el ejemplo: name1 y name3 también existen en la segunda tabla, por lo tanto, sus nuevos nombres son los mismos en ambas tablas (x1, x3).

Estoy buscando solución en bash o tcl (se prefiere bash)

0
Narek Atayan 19 mar. 2017 a las 22:34

2 respuestas

La mejor respuesta

Una cosa que puede hacer es usar awk dentro de un script de shell para realizar un seguimiento de la asignación entre los nombres originales y los nombres recién generados. Este script awk en particular trata el primer archivo de manera diferente al comparar NR y FNR variables integradas que cuentan el número total de registros procesados y el número de registros procesados en el archivo actual, respectivamente. Más información sobre este truco aquí: https://unix.stackexchange.com/questions/106645 / processing-two-files-using-awk

Básicamente, este programa realiza un seguimiento de un contador c y un diccionario name que asigna el nombre original al nuevo (que es solo c con un prefijo de "x") .

También hay dos tipos de líneas. Las líneas de encabezado comienzan con "-" o " ", que se ignoran y se imprimen tal cual.

Es posible que deba dividir el archivo después, a menos que se suponga que los archivos están concatenados.

#!/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

Tenga en cuenta que este programa no formatea, awk tiene una función printf que puede usarse para formatear datos con un número fijo de columnas.

1
Community 13 abr. 2017 a las 12:36

Tcl: usa un diccionario. Si el nombre ya existe. Si no, agréguelo al diccionario. De cualquier manera, dé el nombre de reemplazo.

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]
}

Si las globales te molestan, puedes ocultarlas en un espacio de nombres:

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]
    }
}

Documentación:! (operador) ,dict,global,if,espacio de nombres,proc,return,conjunto,variable

1
Peter Lewerin 19 mar. 2017 a las 21:23