在相同位置查找和替换匹配的字母

时间:2018-01-14 06:44:43

标签: regex string bash perl

这是一个正则表达式问题,但我在Wiki页面找不到适合我的案例的选项,所以我决定在这里问一下。可能是一个简单的未知选项正则表达式可以解决我的情况。

我有一个日志文件(a.txt),它有多行字符串。我想比较每两行(第1和第2,第3和第4 ......)并将匹配的字母(不是字符串)替换为"。"(或任何特殊字符)。

A.TXT:

ExpectedConditions.presenceOfElementLocated()

的Result.txt:

isDisplay

这可能是两个字符串的XOR问题,所以我尝试了这种方式,但它需要转换为ASCII然后XOR是可行的(可能这种方法不对)。我认为有一种非常简单的方法可以用SED / PERL完成这项工作。任何建议和/或指导表示赞赏。感谢您阅读我的问题。

4 个答案:

答案 0 :(得分:5)

Perl使用bitwise operators

#!/usr/bin/env perl

use strict;
use warnings;
use v5.10;

while ( !eof(DATA) ) {
    chomp( my $line1 = <DATA> );
    chomp( my $line2 = <DATA> );

    ( my $uniq_mask = $line1 ^ $line2 ) =~ s/[^\0]/\xFF/g;

    my $uniq1 = $line1;
    my $uniq2 = $line2;

    for ( $uniq1, $uniq2 ) {
        $_ &= $uniq_mask;
        s/\0/./g;
    }

    say for $line1, $line2, $uniq1, $uniq2, '';
}

__DATA__
1100110010
1100101100
0011001100
0110101111

输出:

1100110010
1100101100
.....1001.
.....0110.

0011001100
0110101111
.0.10...00
.1.01...11

答案 1 :(得分:2)

这是一个Perl版本:

#!/usr/bin/env perl

# always use these two
use strict;
use warnings;

# handle errors in open and close
use autodie; # See http://perldoc.perl.org/autodie.html

while( ! eof( DATA ) ){
    chomp( my $line1 = <DATA> );
    chomp( my $line2 = <DATA> );

    my @data1 = split //, $line1;
    my @data2 = split //, $line2;

    # do the first
    for my $i ( 0 .. $#data1 ){
        if( $data1[$i] eq $data2[$i] ){
            print ".";
        }else{
            print $data1[$i];
        }
    }
    print "\n";

    # do the second
    for my $i ( 0 .. $#data2 ){
        if( $data1[$i] eq $data2[$i] ){
            print ".";
        }else{
            print $data2[$i];
        }
    }
    print "\n";

}

__DATA__
1100110010
1100101100
0011001100
0110101111

答案 2 :(得分:1)

既然提到了xor,

my $xor = $s1 ^ $s2;
my $mask = $xor =~ tr/\x01-\xFF/\xFF/r;
my $dots = $xor =~ tr/\x00\x01-\xFF/.\x00/r;

say $s1 & $mask | $dots;
say $s2 & $mask | $dots;

此代码假定换行符已被删除,并假设$s1$s2的长度相同。

答案 3 :(得分:0)

以下是sed中的答案 它假定线总是等长,只包含“0”和“1” 仅“0”或“1”尤其涵盖假设“否”>“任何地方”。
对于不同的长线似乎有些强大(我做了一些简单的测试),但不能保证。

sed -En "N;s/^(.*)\n(.*)$/>\1\n>\2/;:a;s/>([01])(.*)\n(.*)>\1/.>\2\n\3.>/;ta;s/>([^$\n])/\1>/g;ta;s/>//g;p"

代码意味着:

  • -En使用扩展正则表达式,不自动打印
  • N立即查看此行及下一行
  • 由于缺少s///
  • g执行单一替换,非全局替换
  • 第一次替换在两行的开头引入了一个游标“>
  • :a引入了循环标签
  • 第二次更换确实取代了 光标,0或1,第一行的其余部分,
    第二行开始,光标,相同0或1
    通过
    点,光标,第一行的其余部分,
    第二行开始,点光标
  • 然后,如果成功替换,则循环到标签
  • 否则第三次替换将两个游标向前移动并循环,
    除非到达行尾
  • 第四个替换remos the the游标
  • p打印结果

您的样本输入的输出(与样本输入交错):

1100110010
1100101100
.....1001.
.....0110.
0011001100
0110101111
.0.10...00
.1.01...11

第二行的输出与您指定的所需输出不同,“。”而不是“0”,
但是在充分尊重的情况下,我认为你想要的输出是不正确的。

使用:GNU sed版本4.2.1