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)mawk
とoriginal-awk
すべて必要に応じて行われた。
答え4
テーマの変形
echo 'aaabefhhhhhthkkd' |
awk '{while (length()>0) {t=substr($0,1,1); printf (gsub( t ,"")==1)?t:""} print}'
beftd
$0
空になるまで最初の文字を交換して使用し、""
交換が一度だけ発生した場合は印刷します。