Mam ciąg "re\x{0301}sume\x{0301}"
(który drukuje w następujący sposób: re & # x0301; sume & # x0301;) i chcę go odwrócić do "e\x{0301}muse\x{0301}r"
(e & # x0301; muse & # x0301; r). Nie mogę użyć Perla reverse
, ponieważ traktuje on takie znaki jak "\x{0301}"
jako osobne znaki, więc otrzymuję "\x{0301}emus\x{0301}er"
(& # x0301; emus & # x0301; er). Jak mogę odwrócić ciąg, ale nadal szanować łączące się znaki?Jak mogę odwrócić ciąg zawierający kombinację znaków w Perlu?
Odpowiedz
najlepszą odpowiedzią jest użycie Unicode::GCString, as Sinan points out
zmodyfikowałem przykład Chas trochę:
- Ustaw kodowanie na STDOUT, aby uniknąć ostrzeżeń "szeroki znak w druku";
- Użyj pozytywny twierdzenie uprzedzoną (i nie tryb retencji separatora) w
split
(nie działa po 5.10, najwyraźniej, więc usunąłem go)
Jest to w zasadzie to samo, z kilkoma ulepszeniami.
use strict;
use warnings;
binmode STDOUT, ":utf8";
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print <<HERE;
original: [$original]
wrong: [$wrong]
right: [$right]
HERE
Można użyć \X special escape (mecz non-łączącą charakter i wszystkie z następujących znaków łączących) z split
aby zrobić listę grafemami (z pustych strunach między nimi), odwrócić listę grafemami, następnie join
je z powrotem razem:
#!/usr/bin/perl
use strict;
use warnings;
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print "original: $original\n",
"wrong: $wrong\n",
"right: $right\n";
Dla tych mylić (jak ja na początku) o tym, dlaczego są puste ciągi między grafemami, to dlatego, że 'split' jest odwrócony: wykorzystuje dane to jest potrzebne jako separator. Pusty sznur to "od" dwóch grafemów. Dopiero włączenie separatora powoduje, że miesza się grafem z "prawdziwym" wynikiem - paczką pustych strun. Alternatywną (i nieco szybszą) metodą uniknięcia tego jest użycie 'm // g' do przechwytywania grafem zamiast:' join '', reverse $ original = ~/(\ X)/g' –
Aby wyjaśnić komentarz Michaela , kiedy używasz nawiasów pamięci w wyrażeniu, które dajesz podzielić, uruchamiasz "tryb zatrzymywania separatora". Odzyskujesz to, co dzieje się między częściami, które dzielisz. Nie musisz tego jednak robić. Wzorzec (? = \ X) robi to samo bez dodatkowych bitów. Nie, że pusty sznur ma tak naprawdę znaczenie dla małych strun. –
Masz prawo zwrócić uwagę na "tryb przechowywania separatora", dziękuję, to było pomocne. Jednak (? = \ X) nie jest równoważny. Jako dowód, następujące dwa przykłady: podzielone/(a) /, "abc" jest równoważne podzielone/(= A)/"abc" i podzielić/(b + c) /, "abbcd" nie jest równoznaczne z split/(? = b + c) /, "abbcd" – Flimm
Niektóre z pozostałych odpowiedzi zawierają elementy, które nie działają dobrze. Oto działający przykład testowany w Perlu 5.12 i 5.14. Niewyznaczenie trybu bin spowoduje, że dane wyjściowe będą generować komunikaty o błędach. Użycie pozytywnej asercji z wyprzedzeniem (i bez trybu zatrzymania separatora) w split spowoduje, że dane wyjściowe będą niepoprawne na moim MacBooku.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'unicode_strings';
binmode STDOUT, ":utf8";
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print "original: $original\n",
"wrong: $wrong\n",
"right: $right\n";
Można użyć Unicode::GCString:
Unicode :: GCString traktuje ciąg Unicode jako sekwencja rozbudowanych klastrów grafem zdefiniowane przez standard Unicode załącznika nr 29 [UAX # 29].
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use feature 'say';
use open qw(:std :utf8);
use Unicode::GCString;
my $x = "re\x{0301}sume\x{0301}";
my $y = Unicode::GCString->new($x);
my $wrong = reverse $x;
my $correct = join '', reverse @{ $y->as_arrayref };
say "$x -> $wrong";
say "$y -> $correct";
wyjściowa:
résumé -> ́emuśer résumé -> émusér
- 1. Jak mogę odczytać ciąg znaków zawierający spacje w C?
- 2. Jak przekonwertować ciąg znaków szesnastkowy na ciąg bajtów w Perlu?
- 3. odwrócić ciąg w Pythonie
- 4. Jak mogę wstępnie przydzielić ciąg w Perlu?
- 5. Jak utworzyć ciąg znaków zawierający filtr na Neo4j Cypher
- 6. Jak mogę usunąć ostatnie siedem znaków wartości skrótu w Perlu?
- 7. Jak przekonwertować ciąg na liczbę w Perlu?
- 8. Jak zawijać ciąg tekstowy w Perlu?
- 9. Jak odwrócić słowa w ciągu znaków?
- 10. Jak zamienić ciąg w java zawierający kropkę?
- 11. Konwertuj ciąg znaków UTF8 na ASCII w Perlu
- 12. Jaki jest najdłuższy ciąg jaki mogę mieć?
- 13. Czy mogę rozpakować ciąg znaków?
- 14. Jak mogę odwrócić ruch kursora w pythonie?
- 15. Jak uzyskać ciąg żądania zawierający parametry
- 16. Jak mogę sprawdzić daty w Perlu?
- 17. Czy mogę użyć polecenia rozpakuj, aby podzielić ciąg znaków na znaki w Perlu?
- 18. Znaleźć kombinację znaków diakrytycznych dla postaci w punkcie w emacs
- 19. Jak wstawić wiele białych znaków w Perlu?
- 20. Jak obcinać ciąg do określonej długości w perlu?
- 21. Jak skompresować ciąg gzip w Perlu
- 22. Jak mogę zaimplementować uniksowy grep w Perlu?
- 23. Jak odwrócić wyjście sed?
- 24. Konwersja serię pandy zawierający ciąg boolean
- 25. Znajdź klucz zawierający ciąg w słowniku swift
- 26. Jak mogę odwrócić trasę pliku statycznego?
- 27. Jak mogę odwrócić ten prosty wyglądający algorytm?
- 28. Jak mogę odwrócić wartości min-max UISlider?
- 29. Jak mogę odwrócić CALayer za pomocą CATransform3D?
- 30. jak przesunąć ciąg na prawo i odwrócić go w pythonie?
Wow. Lubię perla, ale to podzielone wyrażenie jest dość magiczne. Moją pierwszą myślą była "brutalna siła": wykonaj funkcję, aby zrobić to, co robi podział - zwróć listę ciągów znaków, z których każda stanowi logiczną postać. Jakkolwiek dostaniesz tę listę (wywołaj ją @x), na szczęście oczywiście następuje część join ('', reverse (@x)). – Roboprog
Magiczne? Jak to? To tylko regex bez efektów ubocznych i robi dokładnie to, co widzisz. Jeśli uważasz, że to magia, nie widziałaś prawdziwej czarnej sztuki Perla. Można to nazwać sprytnym (choć nie chciałbym), ale nie jest magiczny. To prawdopodobnie coś, czego nigdy nie używałeś. –
Próbowałem uruchomić ten przykład przy użyciu Perl v5.12.4 i nie działało. Używałem/(\ X)/zamiast tego. Zainteresowana, czy ta odpowiedź działała w poprzednich wersjach Perla, czy też po prostu tęskniliśmy za oczywistością? – Flimm