如何删除所有仅包含重复字符的行?

如何删除所有仅包含重复字符的行?

例如:

22111155
44788
56667775
aannmmmm88
66h1122
PPDd88

输出应该是:

44788      # 7 is not repeated
66h1122    # letter h is not repeated 
PPDd88     # letters D or d are not repeated

删除所有字符在同一行中至少重复两次的行。

如果同一行中有任何未重复的字符,则仅打印该行。

答案1

perl

perl -ne 'my %count;
          $count{$_}++ for /./g;
          print if grep {$_ == 1} values %count'

sed

sed '
/./!d;h;s/$/\
/
:1
  s/\(.\)\(.*\)\1\(.*\n\)/\2\3\1/
  s/\(.\)\1*\(.*\n.*\1\)/\2/
t1
/^\n/d;g'

我们将模式空间分成两行。重复的字符将循环移动到第二行。如果最后第一行不为空,我们就打印记录。

答案2

sed -e '
    /\n/!{h;s/^/\n/;}
    /^\n$/d
    /^\n\(.\).*\1/!{g;b;}
    :b;s/^\(\n\(.\).*\)\2/\1/;tb
    s/\n./\n/;s/^/\n/;D
'

解释:

  • 在图案的开头放置一个标记\n,该标记在此过程中会向右移动。
  • 我们设置一个无限循环并在循环内提​​供两个出口。
  • 第一,如果在此过程中整个字符串被清空,只留下标记,我们退出时知道该字符串包含所有重复的内容。
  • 二、如果在这个过程中我们发现字符串中的第一个元素不重复。意味着至少有一个非重复的位置。因此这一行需要打印。我们取出在开始该过程之前存放在保留区域的原件。
  • 另一种方法是,第一个元素在字符串中的某个位置至少有一个重复项,我们将其t-loop从字符串中完全清除该元素的存在。

另一种方法是使用Perl如图所示:

perl -lne '
    my $s = $_;
    s/\Q$1\E//g while $s =~ /(.)(?=.*?\1)/g;
    print $s if /./;
'

在这里,我们复制该行,并不断查找重复的元素,并不断将它们从原始行中剥离。 while 循环结束后,我们打印副本,前提是行中保留有一些内容(这意味着,不重复的内容被留下了)。

答案3

perl one-liner:删除所有字符对,如果有剩余字符则打印该行。

perl -lne '($copy = $_) =~ s/(.)\1//g; print if $copy' file

正如你所说,上面是错误的:它会错误地打印“56667775”,因为该答案只查看的字符。查看 Stéphane 的答案是否正确。

答案4

使解决方案适应您的情况最近的问题:

awk '
        {split ("", N)                                          # delete N array
         L = 0                                                  # reset boolean L used for print decision
         for (i=1; i<=length; i++)  N[substr($0, i, 1)]++       # calculate count of characters
         for (n in N) if (N[n] < 2)     {L = 1                  # for non-duplicate chars: set print decision
                                         break                  # and quit the for loop
                                        }
        }
L                                                               # print if non-duplicate chars exist
' file
44788
66h1122
PPDd88

相关内容