如何从Bash中的string中删除重复的字符?

我有一个string

cabbagee 

我想删除重复的字符。 如果我使用tr -s,它将删除序列中的重复字符。 但是我的期望输出是

 cabge 

感谢任何人都可以帮助我。

提供的答案是正确的,但我不能使用awk,所以我用:

 #!/usr/bin/bash key=$1 len=${#key} mkey="" for (( c=0; c<len; c++ )) do tmp=${key:$c:1} echo $mkey | grep $tmp >/dev/null 2>&1 if [ "$?" -eq "0" ]; then echo "Found $tmp in $mkey" else mkey+=$tmp fi done echo $mkey 

你可以用awk吗?

 awk -v FS="" '{ for(i=1;i<=NF;i++)str=(++a[$i]==1?str $i:str) } END {print str}' <<< "cabbagee" cabge 

其他几种方式:

gnu awk

 awk -v RS='[az]' '{str=(++a[RT]==1?str RT: str)}END{print str}' <<< "cabbagee" cabge 

 awk -v RS='[az]' -v ORS= '++a[RT]==1{print RT}END{print "\n"}' <<< "cabbagee" cabge 

gnu sedawk

 sed 's/./&\n/g' <<< "cabbagee" | awk '!a[$1]++' | sed ':a;N;s/\n//;ba' cabge 

你编辑了你的文章,并发布了一个丑陋的答案。 在纯粹的Bash中,一个更简单,工作更有效率的方法:

 #!/bin/bash key=$1 mkey=$key for ((i=0;i<${#mkey};++i)); do c=${mkey:i:1} tailmkey=${mkey:i+1} mkey=${mkey::i+1}${tailmkey//"$c"/} done echo "$mkey" 

你的脚本为什么坏了? 这里有一些你的失败,而我的失败。 为了示范,我把你的脚本banana和我的gorilla叫做。 噢,因为我不是那么卑鄙,所以我解决了你的脚本所带来的简单的引用问题(这个问题简单地与*字符打断),并且评论了洪泛部分:

 #!/usr/bin/bash key=$1 len=${#key} mkey="" for (( c=0; c<len; c++ )); do tmp=${key:$c:1} echo "$mkey" | grep "$tmp" >/dev/null 2>&1 # Added quotes here! if [ "$?" -eq "0" ]; then : # echo "Found $tmp in $mkey" # Commented this to remove flooding else mkey+=$tmp fi done echo "$mkey" # Added quotes here! 

所以我们走吧:

 $ ./banana '^' $ ./gorilla '^' '^' 

是的,那是因为^是grep的正则表达式中使用的字符。 类似的东西发生在$ ,也与.

 $ ./banana 'a.' a $ ./gorilla 'a.' a. 

现在反斜杠也会导致问题:

 $ ./banana '\\' \\ $ ./gorilla '\\' \ 

(删除>/dev/null 2>&1部分以查看grep: Trailing backslash错误)。 同样的事情发生在[

不要提到你的脚本是非常低效的! 它多次调用grep 。 在这方面,我的情况好一些:

 $ time for i in {1..200}; do ./banana cabbage; done &>/dev/null real 0m3.028s user 0m0.216s sys 0m0.464s $ time for i in {1..200}; do ./gorilla cabbage; done &>/dev/null real 0m0.878s user 0m0.172s sys 0m0.324s 

不错,呃?

另一个基准是自己说的:用一个长串,例如Lorem Ipsum的一段:

 $ time ./banana 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.' Lorem ipsudlta,cngDSMqvhPbNAUfCI real 0m1.464s user 0m0.104s sys 0m0.224s $ time ./gorilla 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.' Lorem ipsudlta,cng.DSMqvhPbNAUfCI real 0m0.013s user 0m0.000s sys 0m0.008s 

这是因为banana正在为输入字符串的每个字符调用一个grep ,而gorilla会动态地执行删除。 (我不打算提到banana错过了这段时间)。

怎么样:

 echo "cabbagee" | sed 's/./&\n/g' | perl -ne '$H{$_}++ or print' | tr -d '\n' 

这产生:

 cabge 

上面的代码将你的字符串的字符分割成单独的行( sed 's/./&\n/g' ),然后使用一些perl魔法(credit unix工具从文件中删除重复的行 )去除所有重复的行。 最后, tr -d '\n'删除我们添加的换行符以实现所需的输出。

可能需要修改一下你的具体目的,这感觉非常哈克,但似乎完成工作。

祝你好运。

你可以使用grep -o .\n分割每个字符然后只收集在bash中没有看到的字符:

 grep -o . <<<'cabbagee' | \ { while read c; do [[ "$s" = *$c* ]] || s=$s$c; done; echo $s; } 

我不确定你在做什么语言,但是你总是可以做一个循环来完成这个字符串。 然后做一个if循环,说明如果yourstring.charAt(i).equals(yourstring.char(i + 1){replace(yourstring.char(i + 1),“”))}所以基本上要经过一个循环,在当前索引处等于下一个索引处的字符,然后用空字符串替换下一个索引:“”。