man*_*anu 11 regex string perl duplicates
如何删除重复的字符并仅保留唯一的字符.例如,我的输入是:
EFUAHUU
UUUEUUUUH
UJUJHHACDEFUCU
Run Code Online (Sandbox Code Playgroud)
预期产出是:
EFUAH
UEH
UJHACDEF
Run Code Online (Sandbox Code Playgroud)
我遇到perl -pe's/$1//g while/(.).*\/'的很棒,但它甚至可以删除输出中出现的单个字符.
cod*_*ict 15
这可以使用积极的前瞻来完成:
perl -pe 's/(.)(?=.*?\1)//g' FILE_NAME
Run Code Online (Sandbox Code Playgroud)
使用的正则表达式是: (.)(?=.*?\1)
. :匹配任何char.():记住匹配的单个字符.(?=...) :+ ve预测.*? :匹配两者之间的任何东西\1 :记住的比赛.(.)(?=.*?\1):匹配并记住任何字符串,如果它稍后再次出现在字符串中.s/// :Perl做替换的方式.g:全局替换...在第一次替换后不会停止.s/(.)(?=.*?\1)//g :这将仅在字符串中稍后再次出现该字符时从输入字符串中删除char.这不会保持输入中char的顺序,因为对于输入字符串中的每个唯一char,我们保留其最后一次出现而不是第一次出现.
为了保持相对顺序的完整性,我们可以KennyTM在其中一条评论中做到:
Perl的一行是:
perl -ne '$_=reverse;s/(.)(?=.*?\1)//g;print scalar reverse;' FILE_NAME
Run Code Online (Sandbox Code Playgroud)
由于我们print在反转后手动执行,因此我们不使用该-p标志,而是使用该-n标志.
我不确定这是否是最好的单行代码.如果他们有更好的选择,我欢迎其他人编辑这个答案.
如果Perl不是必须的,你也可以使用awk.这是针对awk发布的Perl one liners的有趣基准.对于具有300万++行的文件,awk快10秒以上
$ wc -l <file2
3210220
$ time awk 'BEGIN{FS=""}{delete _;for(i=1;i<=NF;i++){if(!_[$i]++) printf $i};print""}' file2 >/dev/null
real 1m1.761s
user 0m58.565s
sys 0m1.568s
$ time perl -n -e '%seen=();' -e 'for (split //) {print unless $seen{$_}++;}' file2 > /dev/null
real 1m32.123s
user 1m23.623s
sys 0m3.450s
$ time perl -ne '$_=reverse;s/(.)(?=.*?\1)//g;print scalar reverse;' file2 >/dev/null
real 1m17.818s
user 1m10.611s
sys 0m2.557s
$ time perl -ne'my%s;print grep!$s{$_}++,split//' file2 >/dev/null
real 1m20.347s
user 1m13.069s
sys 0m2.896s
Run Code Online (Sandbox Code Playgroud)