正则表达式匹配文件中的唯一单词

Pat*_*ert 3 regex linux perl grep

要在文件中使用"UNIQUE:"为唯一单词添加前缀,我尝试使用perl regex命令,如:

perl -e 'undef $/;while($_=<>){s/^(((?!\b\3\b).)*)\b(\w+)\b(((?!\b\3\b).)*)$/\1UNIQUE:\3\4/gs;print $_;}' demo
Run Code Online (Sandbox Code Playgroud)

在包含以下内容的演示文件

watermelon banana
apple pear pineapple orange mango
strawberry cherry
kiwi pineapple lemon cranberry watermelon
orange plum cherry
kiwi banana plum
mango cranberry apple
lemon
Run Code Online (Sandbox Code Playgroud)

输出是:

watermelon banana
apple pear pineapple orange mango
strawberry cherry
kiwi pineapple lemon cranberry watermelon
orange plum cherry
kiwi banana plum
mango cranberry apple
UNIQUE:lemon
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果提前使用,似乎没有处理\ 3反向引用.

是否有另一种方法可以通过另一个正则表达式或Linux机器上的其他常用命令实现此目的?(grep,sed,awk,...)

非常感谢

编辑: 不幸的是,许多解决方案仅适用于所提供的案例而且不完整,我为此道歉,它也应该适用于以下文本:

{watermelon || banana}
apple = ( pear pineapple orange mango )
strawberry cherry
kiwi = pineapple = lemon = cranberry = watermelon
orange - plum = cherry
kiwi = banana + plum
mango = cranberry && apple
lemon
Run Code Online (Sandbox Code Playgroud)

如果它简化了问题,单词可能会以$或@为前缀.

Nie*_*tle 13

我看到你已经在使用Perl了.当你想用哈希计算一些东西总是一个很好的方法......

#!/usr/bin/perl -w
use strict;

my %hash = ();
my $str;

while(<>) {
    $str .= $_;
    $_ =~ s/\W+/ /g;
    map {$hash{$_}++} split ' ', $_;
}

for (keys %hash){
    my $word = $_;
    if($hash{$word}==1) {
        $str =~ s/\($word)/UNIQUE:$word/g;
    }
};

print "$str\n";
Run Code Online (Sandbox Code Playgroud)

这将输出:

{watermelon || banana}
apple = ( UNIQUE:pear pineapple orange mango )
UNIQUE:strawberry cherry
kiwi = pineapple = lemon = cranberry = watermelon
orange - plum = cherry
kiwi = banana + plum
mango = cranberry && apple
lemon

使用正则表达式可能会很困难.您需要两次运行整个文件.一次通过计算所有出现的单词和一次通过来标记唯一单词.

上面的代码片段读取输入一次,但将整个原始文本保存在$ str中 - 如果输入很大,这显然是一个坏主意.


rek*_*o_t 5

只需执行一次正则表达式就无法做到这一点.这样做的原因是因为在第一次替换完成后,内部游标在该匹配结束时移动,并且下次开始匹配时会忘记它背后的内容.事实上,不支持动态后视,因此您无法检查"此单词是否已在此匹配位置之前出现".但是,你可以做的是每次执行正则表达式替换一个单词(因为这样你总是可以在字符串的开头锚定).所以你要做的是运行以下正则表达式,只要它取代了某些东西.

s/^.*?\K(?!UNIQUE:)\b(\w+)\b(?=(?:(?!\b\1\b).)*$)/UNIQUE:\1/s
Run Code Online (Sandbox Code Playgroud)