Perl: 8 lub 10 różnych znaków
s/// rozwiązanie: 10 odrębnych, łącznie 13
(Podobno; patrz poniżej) technika sed zawsze działa również w Perlu i daje nazwę liczby różnych znaków (10):
s/[aeiou]//gi
Na przykład:
$ echo 'This program will remove VOWELS. So we can speak without them.' |
perl -ple 's/[aeiou]//gi'
Ths prgrm wll rmv VWLS. S w cn spk wtht thm.
To 10 różnych znaków, co dowodzi:
$ echo 's/[aeiou]//gi' | perl -nle '@s{split//}=(); print scalar keys %s'
10
Problem z rozwiązaniem sed polega na tym, że nie/i jest on częścią POSIX sed, a zatem nie jest przenośny:
$ echo 'This program will remove VOWELS. So we can speak without them.' |
sed -e 's/[aeiou]//gi'
sed: 1: "s/[aeiou]//gi": bad flag in substitute command: 'i'
To działa na systemie OpenBSD. W przeciwieństwie do tego, bo /ijest rzeczywiście zawsze częścią standardowego Perl, to może liczyć na jego zawsze będąc tam. W przeciwieństwie do sed.
Jeśli chcesz umieścić „y” na liście samogłosek, jest oczywiście o jeden większy, jeśli używasz tej samej techniki:
$ echo 'This nifty program remove any VOWELS. So we easily can speak without them.' |
perl -ple 's/[aeiouy]//gi'
Ths nft prgrm rmv n VWLS. S w sl cn spk wtht thm.
$ echo 's/[aeiouy]//gi' | perl -nle '@s{split//}=(); print scalar keys %s'
11
I jest teraz 14 całkowitych postaci.
tr[][] rozwiązanie: 8 odrębnych 10 ogółem
Możesz także użyć tr///do usunięcia wszystkiego, co pasuje. Perl może nawet używać y///aliasu sed do tr:
y/aeiou//d
który ma teraz 8 różnych znaków, ale nie działa na wielkie litery. W końcu musisz dodać 5 dodatkowych znaków, aby poradzić sobie z mapami wielkości liter:
$ echo 'y/aeiouAEIOU//d' | perl -nle '@s{split//}=(); print scalar keys %s'
13
i oczywiście jest to teraz 15.
Jednak dodanie „y” do miksu jako samogłoski nie zwiększa liczby różnych znaków, tak jak w przypadku s///wersji:
$ echo 'This nifty program remove any VOWELS. So we easily can speak without them.' |
perl -ple 'y/aeiouy//d'
Ths nft prgrm rmv n VOWELS. S w sl cn spk wtht thm.
To wciąż tylko oryginalna 8 odrębnych z 11 wszystkich:
$ echo 'y/aeiouy//d' | perl -nle '@s{split//}=(); print scalar keys %s'
8
EDYCJA : Rachunkowość dla znaków diakrytycznych
A co z danymi wejściowymi Renée’s naïveté? Prawidłowe wyjście powinno oczywiście być Rn’s nvt. Oto jak to zrobić, używając /rflagi v5.14 dla s///:
$ echo 'Renée’s naïveté' |
perl5.14.0 -CS -MUnicode::Normalize -nle 'print NFD($_)=~s/[aeiou]\pM*//rgi'
Rn’s nvt
To 27 różnych znaków:
$ echo 'print NFD($_) =~ s/[aeiou]\pM*//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
27
Możesz to skrócić do 26, jeśli możesz zagwarantować, że korzystasz z wersji co najmniej v5.10, zamieniając printna say:
$ echo 'Renée’s naïveté' |
perl -Mv5.14 -CS -MUnicode::Normalize -nlE 'say NFD($_) =~ s/[aeiou]\pM*//rgi'
Rn’s nvt
$ echo 'say NFD($_) =~ s/[aeiou]\pM*//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
26
Możesz obniżyć go do 22, jeśli nie masz nic przeciwko przeniesieniu znaków diakrytycznych zamiast ich usuwania:
$ echo 'Renée’s naïveté' |
perl -Mv5.14 -CS -MUnicode::Normalize -nlE 'say NFD($_) =~ s/[aeiou]//rgi'
Rń’s n̈vt́
Co jest ... interesujący dla oka, co najmniej. :) Oto jego odrębna liczba:
$ echo 'say NFD($_) =~ s/[aeiou]//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
22
Powodzenia, jeśli jakikolwiek inny język poprawnie radzi sobie z znakami diakrytycznymi przy użyciu mniejszej liczby znaków!