例如:
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