2009-08-28 5 views
11

나는 "re\x{0301}sume\x{0301}" 문자열을 가지고 있는데, 이는 & # x0301; sume & # x0301;과 같이 인쇄됩니다. 그리고 이것을 "e\x{0301}muse\x{0301}r" (e & # x0301; muse & # x0301; r)으로 바꾸고 싶습니다. Perl의 reverse을 사용할 수 없습니다. 왜냐하면 문자가 "\x{0301}"과 같은 문자를 분리 문자로 처리하기 때문에 "\x{0301}emus\x{0301}er" (& # x0301; emus & # x0301; er)이됩니다. 문자열을 뒤집을 수는 있지만 결합 문자는 여전히 존중합니까?Perl에서 결합 문자가 포함 된 문자열을 어떻게 반전시킬 수 있습니까?

답변

8

가장 좋은 대답은 내가 차스의 예를 수정 약간 as Sinan points out


, Unicode::GCString 사용하는 것입니다 :

  • "넓은 문자 인쇄 있음"경고를 피하려면 STDOUT의 인코딩을 설정하십시오. 그것은 기본적으로 고치면 되겠 어의 부부와 함께 같은 일이

  • 는 (분명히, 5.10 후 작동하지 않는, 그래서 그것을 제거) split에 긍정적 예측 주장 (없이 분리 유지 모드)를 사용합니다.

    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 
    
  • +0

    와우. 나는 펄을 좋아하지만 그 분열 된 표정은 꽤 마술 적이다. 나의 첫 번째 생각은 "brute force"였다. 스플릿이하는 일을하는 함수를 만든다. 각각의 엔트리가 논리적 문자를 나타내는 문자열 목록을 반환한다. 그러나 그 목록 (@x라고 부름)을 얻었을 때, 다행히도 join ('', reverse (@x)) 부분이 분명히 뒤 따른다. – Roboprog

    +2

    Magical? 어떻게 그렇게? 그것은 부작용이없는 단지 정규식이며, 여러분이 보는 것과 정확히 일치합니다. 그게 마법이라고 생각한다면 펄의 진정한 흑인 예술을 보지 못했을 것입니다. 영리하다고 생각할 지 모르지만 (그렇다고해도 좋을지도 모르겠지만) 마법 같은 것은 아닙니다. 아마 당신이 사용하지 않은 것일 것입니다. –

    +0

    이 예제를 Perl v5.12.4를 사용하여 실행하려고 시도했지만 작동하지 않았습니다. 대신/(\ X) /를 사용했습니다. 이 답변은 이전 버전의 Perl에서 작동 했습니까? 아니면 확실하지 않습니까? – Flimm

    12

    당신은 join에게 다음의 \X special escape는 제자의 목록을, (그들 사이의 빈 문자열) 제자의 목록을 만들기 위해 split와 (비 결합 문자 다음과 같은 결합 모든 문자와 일치) 역을 다시 사용할 수 있습니다 함께 :

    #!/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"; 
    
    +1

    (내가 처음이었다로)에 대한 제자 사이의 빈 문자열이있는 이유는'split'가 반전 때문입니다 : 그것은 데이터를 사용 그것은 분리 기호로 원했습니다. 빈 문자열은 두 개의 글자 사이에있는 것입니다. 결과에 분리 기호를 포함시키는 것만으로 "실제"결과 - 빈 문자열 묶음과 혼합 된 자수를 얻을 수 있습니다. 'm // g '을 사용하여 대신에 graphemes를 잡아내는 대신 ('join' ', reverse $ original = ~/(\ X)/g') –

    +2

    Michael의 주석을 명확히하기 위해 , 당신이 분할에주는 정규식에서 메모리 괄호를 사용하면 "분리 자 보존 모드"가 트리거됩니다. 당신은 위로 나눠주고있는 부분 사이를 돌아서갑니다. 그러나 그렇게 할 필요는 없습니다. 패턴 (? = \ X)은 여분의 비트없이 동일한 작업을 수행합니다. 빈 문자열은 실제로 작은 문자열에 대해서는별로 중요하지 않습니다. –

    +0

    "분리 기호 보존 모드"를 지적하는 것이 옳습니다. 감사합니다. 도움이되었습니다. 그러나 (? = \ X)는 동일하지 않습니다. 증거를 들어, 이들 두 가지 예를 고려해 스플릿/(a)/"ABC"이 (? = a)/"ABC" 분할/(b + c)/분리와 일치하지 않는/"abbcd"는 split/(? = b + c) /, "abbcd" – Flimm

    0

    일부 답변에는 제대로 작동하지 않는 요소가 포함되어 있습니다. 다음은 Perl 5.12 및 5.14에서 테스트 한 작업 예제입니다. binmode를 지정하지 않으면 출력에서 ​​오류 메시지를 생성합니다. 분할에서 긍정적 인 미리보기 어설 션 (및 분리 자 보존 모드 없음)을 사용하면 Macbook에서 출력이 올바르지 않게됩니다.

    #!/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"; 
    
    2

    당신은 Unicode::GCString을 사용할 수 있습니다 : 유니 코드 표준에 의해 정의 된 확장 된 그래 핀 클러스터의 순서는 [UAX # 29] # 29 부록으로

    유니 코드 :: GCString 유니 코드 문자열을 처리합니다.

    #!/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"; 
    

    출력 : 혼동 사람들을 위해

    résumé -> ́emuśer 
    résumé -> émusér
    관련 문제