2017-03-19 26 views
0

私にとっては、次の問題が奇妙に見えています。Bash/Tcl:テキストファイルの同じ列にあるランダムに生成された名前の名前を変更するにはどうすればよいですか?

は、次のログファイルを考えてみましょう:最初の列から名前が生成され

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

をし、実際に私はそれらについて何も知りません。

質問: はこのような何かを得るために、最初の列からすべての名前の名前を変更する方法:X-ESとの最初の名前の名前を変更することである

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

:「X1、X2を.... "

制限:同じx(i)を重複する名前に割り当てる必要があります。 例:name1とname3も2番目のテーブルに存在するため、新しい名前は両方のテーブル(x1、x3)で同じです。

私はbashやTCLでソリューションを探しています

(bashがより好ましい)

+0

純粋なbash(つまり、読み込んだ組み込み関数を使用し、bashの中で文字列処理を行っています)、あるいは単にbashとcoreユーティリティを使用していますか? ...また、あなたの入力がすでに2つのファイルに分割されていると仮定して、私の答えを書いています。時折繰り返されるヘッダー付きの巨大なログファイルがありますか? –

答えて

1

あなたができることの一つは、元の名前との間のマッピングを追跡するためにシェルスクリプト内awkを使用し、新たにあります生成された名前。この特定のawkスクリプトは、処理されたレコードの合計数と現在のファイルで処理されたレコードの数をそれぞれ数える組み込み変数NRFNRを比較することによって、最初のファイルを異なる方法で処理します。ここでこのトリックについての詳細情報:https://unix.stackexchange.com/questions/106645/processing-two-files-using-awk

は基本的に、このプログラムは、カウンタcと(ちょうどc"x"の接頭辞である)新しいものに元の名前をマップする辞書nameを追跡します。

また、2種類の行があります。ヘッダー行は"-"または" "で始まり、無視され、そのまま印刷されます。

ファイルを連結しない限り、後でファイルを分割する必要があります。

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

このプログラムはない書式設定を行わないことを注意、awkは、列の固定数のフォーマットのデータに使用することができるprintf機能を有しています。

1

Tcl:辞書を使用します。名前が既に存在する場合そうでない場合は、辞書に追加します。いずれにしても、交換名を教えてください。

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

グローバルがお邪魔した場合、あなたが名前空間にそれらを隠すことができます。

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

ドキュメント: ! (operator)dictglobalifnamespaceprocreturnは、 set, variable

関連する問題