与えられた文字列で繰り返されない文字を見つける方法

与えられた文字列で繰り返されない文字を見つける方法

aaabefhhhhhthkkd繰り返されない文字のみを出力に抽出し、順序を維持する必要がある文字列があります。

文字列には大文字または小文字を含めることができます。

入力する:

aaabefhhhhhthkkd

出力:

beftd

上記の目的の出力を取得するには、このロジックをどのように定義する必要がありますか?

このコマンドを試してみましたが、部分的にのみ機能しました。

echo "aaabefhhhhhthkkd" | sed 's/./&\n/g' | uniq

上記の部分実行コマンドの出力:

a
b
e
f
h
t
h
k
d

テストする文字列の例:

String 1: aaabefhhhhhthkkd -> Output -> beftd

String 2: AAAbefhhhhhThkkD -> Output -> befTD 

String 3: AAAbefhMThkkD    -> Output -> befMTD 

答え1

uniq隣接する重複項目に対してのみ機能します。したがって、使用する前に入力を並べ替える必要があります。例:

fold -w1 | sort | uniq -u | paste -sd ''
  • fold -w1あなたと同じですsed 's/./&\n/g'が、不要な改行文字を追加導入しません。
  • sort繰り返される文字を隣接させます。
  • uniq -u-uシングルトンのみを印刷することが重要です。
  • paste -sd ''結果をもう一度行にリンク

ソートのため、すべての場合に所望の出力順序を得ることはできない。

$ echo 'AAAbefhMThkkD' | fold -w1 | sort | uniq -u | paste -sd ''
  DMTbef

独自のソリューションをリリースしたくない場合は、いつでもPerlを使用できますMoreUtils

$ echo 'AAAbefhMThkkD' |
    perl -MList::MoreUtils=singleton -ne 'print singleton split //'
befMTD

答え2

すべてのUNIXシステムのすべてのシェルでawkを使用します。

$ echo 'aaabefhhhhhthkkd' |
    awk '{
        lgth = length()
        for (pos=1; pos<=lgth; pos++) {
            let = substr($0,pos,1)
            if ( gsub(let,"&") == 1 ) {
                printf "%s%s", let, (pos<lgth ? "" : ORS)
            }
        }
    }'
beftd

答え3

awk '
{
  n=split($0, a, "")
  for(i=1; i<=n; i++){
    if(gsub(a[i], "") == 1){ printf("%s", a[i]) }
  }
  print ""
}'
  • n=split($0, a, "")a[1]文字列の最初の文字になり、a[2]2番目の文字などが文字n全体の数です。
  • for(i=1; i<=n; i++):すべての配列を繰り返してみましょうa
  • if(gsub(a[i], "") == 1)a[i]文字列のすべての文字を削除します。文字列から1文字だけ削除された場合、
    • printf("%s", a[i])この文字を印刷してみてください。
  • print ""すべての行が処理された後に改行を印刷します。入力ラインが1つしかない場合、これはオプションです。

シングルライン圧縮の例:

$ awk '{n=split($0,a,"");for(i=1;i<=n;i++)if(gsub(a[i],"")==1)printf("%s",a[i])}' <<< AAAbefhMThkkD
befMTD

注:POSIXは空の文字列の分割を定義しません。しかしgawk(GNU Awk)mawkoriginal-awkすべて必要に応じて行われた。

答え4

テーマの変形

echo 'aaabefhhhhhthkkd' | 
 awk '{while (length()>0) {t=substr($0,1,1); printf (gsub( t ,"")==1)?t:""} print}'

beftd

$0空になるまで最初の文字を交換して使用し、""交換が一度だけ発生した場合は印刷します。

関連情報