如何将两个文件中的字符串对替换为相同的ID?

时间:2010-04-20 10:49:13

标签: shell cygwin grep replace

[Update2] 正如经常发生的那样,任务的范围扩大了很多,因为它可以更好地理解。过时的部分被划掉,您可以在下面找到更新的说明。的 [/ UPDATE2]

我有一对相当大的日志文件,内容非常相似,只是两者之间的某些字符串不同。几个例子:

UnifiedClassLoader3@19518cc | UnifiedClassLoader3@d0357a
JBossRMIClassLoader@13c2d7f | JBossRMIClassLoader@191777e

也就是说,无论第一个文件包含UnifiedClassLoader3@19518cc,第二个文件包含UnifiedClassLoader3@d0357a,依此类推。 [更新] 大约有40对不同的此类标识符。 [/ Update]

UnifiedClassLoader3@19518cc | UnifiedClassLoader3@d0357a
JBossRMIClassLoader@13c2d7f | JBossRMIClassLoader@191777e
Logi18n@177060f             | Logi18n@12ef4c6
LogFactory$1@15e3dc4        | LogFactory$1@2942da

也就是说,只要第一个文件包含UnifiedClassLoader3@19518cc,第二个文件包含UnifiedClassLoader3@d0357a,依此类推。请注意,所有这些字符串都在长行文本中,并且它们出现在许多行中,彼此混合在一起。大约有4000对不同的此类标识符,每个文件的大小约为34 MB。因此,性能也成为一个问题。

我想用相同的ID替换它们,以便我可以发现两个文件之间真正重要的区别。即我想用UnifiedClassLoader3@19518cc替换file2中UnifiedClassLoader3@d0357a和{2}中UnifiedClassLoader3@1的所有匹配项;文件1中的Logi18n@177060f和文件2中的Logi18n@12ef4c6都出现Logi18n@2等。计数器12是任意选择 - 唯一的要求是那里是旧字符串和新字符串之间的一对一映射(即,相同的字符串总是被相同的值替换,并且没有不同的字符串被相同的值替换)。

使用Cygwin shell,到目前为止,我设法列出其中一个文件中出现的所有不同标识符 <击>

<击>
grep -o -e 'ClassLoader[0-9]*@[0-9a-f][0-9a-f]*' file1.log | sort | uniq

<击>

grep -o -e '[A-Z][A-Za-z0-9]*\(\$[0-9][0-9]*\)*@[0-9a-f][0-9a-f]*' file1.log
    | sort | uniq

但是,现在原始订单丢失了,所以我不知道哪一个是哪一个ID在另一个文件中。使用grep -n我可以获得行号,因此排序将保留外观的顺序,但是我不能清除重复的事件。不幸的是,grep不能只打印模式的第一个匹配。

我想我可以将上述命令生成的标识符列表保存到文件中,然后使用grep -n | head -n 1遍历文件中的模式,连接结果并再次对它们进行排序。结果就像是

2 ClassLoader3@19518cc
137 ClassLoader@13c2d7f
563 ClassLoader3@1267649
...

然后我可以(使用sed本身)按下这个sed命令,如

sed -e 's/ClassLoader3@19518cc/ClassLoader3@2/g' 
    -e 's/ClassLoader@13c2d7f/ClassLoader@137/g' 
    -e 's/ClassLoader3@1267649/ClassLoader3@563/g' 
    file1.log > file1_processed.log

,类似于file2。

然而,在我开始之前,我想验证我的计划是最简单的解决方案。

这种方法有什么缺陷吗?有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

我认为这样做,或者至少接近

#!/bin/sh
for PREFIX in file1 file2
do
    cp ${PREFIX}.log /tmp/filter.$$.txt
    FILE_MAP=`egrep -o -e 'ClassLoader[0-9a-f]*@[0-9a-f]+' ${PREFIX}.log | uniq | egrep -n .`
    for MAP in `echo $FILE_MAP`
    do
        NUMBER=`echo $MAP | cut -d : -f 1` 
        WORD=`echo $MAP | cut -d : -f 2`
        sed -e s/$WORD/ClassLoader@$NUMBER/g /tmp/filter.$$.txt > ${PREFIX}_processed.log
        cp ${PREFIX}_processed.log /tmp/filter.$$.txt
    done
    rm /tmp/filter.$$.txt
done

如果您对其运作方式和原因有疑问,请与我们联系。

这是我的测试数据和输出

file1.log:

A1
UnifiedClassLoader3@a45bc1
A2
UnifiedClassLoader3@a45bc1
A3
UnifiedClassLoader3@a45bc1
A4
JBossRMIClassLoader@bc450a
A5
JBossRMIClassLoader@bc450a
A6
JBossRMIClassLoader@bc450a

B1
UnifiedClassLoader3@a45bc2
B2
UnifiedClassLoader3@a45bc2
B3
UnifiedClassLoader3@a45bc2
B4
JBossRMIClassLoader@bc450b
B5
JBossRMIClassLoader@bc450b
B6
JBossRMIClassLoader@bc450b

C1
UnifiedClassLoader3@a45bc3
C2
UnifiedClassLoader3@a45bc3
C3
UnifiedClassLoader3@a45bc3
C4
JBossRMIClassLoader@bc450c
C5
JBossRMIClassLoader@bc450c
C6
JBossRMIClassLoader@bc450c

file2.log(除了“C”集之外的类似模式重复“A”集)

A1
UnifiedClassLoader3@d0357a
A2
UnifiedClassLoader3@d0357a
A3
UnifiedClassLoader3@d0357a
A4
JBossRMIClassLoader@191777e
A5
JBossRMIClassLoader@191777e
A6
JBossRMIClassLoader@191777e

B1
UnifiedClassLoader3@d0357b
B2
UnifiedClassLoader3@d0357b
B3
UnifiedClassLoader3@d0357b
B4
JBossRMIClassLoader@191777f
B5
JBossRMIClassLoader@191777f
B6
JBossRMIClassLoader@191777f

C1
UnifiedClassLoader3@d0357a
C2
UnifiedClassLoader3@d0357a
C3
UnifiedClassLoader3@d0357a
C4
JBossRMIClassLoader@191777e
C5
JBossRMIClassLoader@191777e
C6
JBossRMIClassLoader@191777e

处理后你得到file1_processed.log

A1
UnifiedClassLoader@1
A2
UnifiedClassLoader@1
A3
UnifiedClassLoader@1
A4
JBossRMIClassLoader@2
A5
JBossRMIClassLoader@2
A6
JBossRMIClassLoader@2

B1
UnifiedClassLoader@3
B2
UnifiedClassLoader@3
B3
UnifiedClassLoader@3
B4
JBossRMIClassLoader@4
B5
JBossRMIClassLoader@4
B6
JBossRMIClassLoader@4

C1
UnifiedClassLoader@5
C2
UnifiedClassLoader@5
C3
UnifiedClassLoader@5
C4
JBossRMIClassLoader@6
C5
JBossRMIClassLoader@6
C6

和file2_processed.log

A1
UnifiedClassLoader@1
A2
UnifiedClassLoader@1
A3
UnifiedClassLoader@1
A4
JBossRMIClassLoader@2
A5
JBossRMIClassLoader@2
A6
JBossRMIClassLoader@2

B1
UnifiedClassLoader@3
B2
UnifiedClassLoader@3
B3
UnifiedClassLoader@3
B4
JBossRMIClassLoader@4
B5
JBossRMIClassLoader@4
B6
JBossRMIClassLoader@4

C1
UnifiedClassLoader@1
C2
UnifiedClassLoader@1
C3
UnifiedClassLoader@1
C4
JBossRMIClassLoader@2
C5
JBossRMIClassLoader@2
C6
JBossRMIClassLoader@2