Обрезать юникодные пробелы в PHP 5.2 - PullRequest
22 голосов
/ 12 ноября 2010

Как я могу обрезать string(6) " page", где первый пробел представляет собой неразрывный пробел 0xc2a0?

Я пробовал trim() и preg_match('/^\s*(.*)\s*$/u', $key, $m);.

Еще один вопрос: как я могу надежно скопировать эти символы? Кажется, они преобразованы в «нормальные» пробелы, что затрудняет их отладку.

Ответы [ 6 ]

43 голосов
/ 12 ноября 2010
preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u','',$str);
6 голосов
/ 12 ноября 2010

PCRE свойства юникода свойства могут быть использованы для достижения этого

Вот код, с которым я играл и, кажется, делает то, что вы хотите:

<?php
function unicode_trim ($str) {
    return preg_replace('/^[\pZ\pC]+([\PZ\PC]*)[\pZ\pC]+$/u', '$1', $str);
}

$key = chr(0xc2) . chr(0xa0) . '#page#' . chr(0xc2) . chr(0xa0);

var_dump(unicode_trim($key));

Результат

[~]> php e.php
string(6) "#page#"

Пояснение:

\ р {хх} персонаж со свойством xx \ Р {хх} символ без свойства xx

Если у хх только один символ, то {} можно отбросить, например, \ p {Z} совпадает с \ pZ

Z обозначает все разделители, C обозначает все «другие» символы (например, управляющие символы)

5 голосов
/ 13 ноября 2010

В существующем решении упоминаются только \pZ символы. Однако есть шесть символов пробела Unicode, которые выходят за рамки этого свойства:

% unichars '\p{WhiteSpace}' '\PZ'
 --    9 0009 CHARACTER TABULATION
 --   10 000A LINE FEED (LF)
 --   11 000B LINE TABULATION
 --   12 000C FORM FEED (FF)
 --   13 000D CARRIAGE RETURN (CR)
 --  133 0085 NEXT LINE (NEL)

Все эти шесть относятся к типу \pC и, в частности, к типу \p{Cc}. Однако есть пятьдесят девять непробельных символов, которые также \p{Cc}:

% unichars '\P{WhiteSpace}' '\p{Cc}' | wc -l
      59

Простая версия моего собственного теста того, является ли что-то печатным символом или нет, это просто [\pZ\pC]; это то, что unichars использует, например.

Более тщательный тест должен учитывать, должно ли что-либо занимать 0, 1 или 2 позиции печати. Это требует рассмотрения того, является ли это объединяющей меткой, которая является свойством \pM, а также имеет ли она свойства половинной или полной ширины. Например:

% uniprops ff5e ffeb
U+FF5E ‹~› \N{ FULLWIDTH TILDE }:
    \pS \p{Sm}
    All Any Assigned InHalfwidthAndFullwidthForms Changes_When_NFKC_Casefolded
       CWKCF Common Zyyy Sm S Gr_Base Grapheme_Base Graph GrBase Math
       Math_Symbol Print Symbol
U+FFEB ‹→› \N{ HALFWIDTH RIGHTWARDS ARROW }:
    \pS \p{Sm}
    All Any Assigned InHalfwidthAndFullwidthForms Changes_When_NFKC_Casefolded
       CWKCF Common Zyyy Sm S Gr_Base Grapheme_Base Graph GrBase Math
       Math_Symbol Print Symbol

Для этого вам необходимо использовать недвоичное свойство East Asian Width. Это применимо:

% uniprops -l | grep -i width
Block:Halfwidth_And_Fullwidth_Forms
InHalfwidthAndFullwidthForms
East_Asian_Width:A
East_Asian_Width=Ambiguous
East_Asian_Width:Ambiguous
East_Asian_Width:F
East_Asian_Width=Fullwidth
East_Asian_Width:Fullwidth
East_Asian_Width:H
East_Asian_Width=Halfwidth
East_Asian_Width:Halfwidth
East_Asian_Width=Neutral
East_Asian_Width:Na
East_Asian_Width=Narrow
East_Asian_Width:Narrow
East_Asian_Width:Neutral
East_Asian_Width:W
East_Asian_Width=Wide
East_Asian_Width:Wide

Они имеют такие сокращения, как \p{Ea=F} и \p{Ea=H}. Есть куча таких:

% uninames '(FULL|HALF)WIDTH' | wc -l
     454

Конечно, вы не должны использовать имена для этих вещей, но для свойств:

% unichars '[\p{Ea=F}\p{Ea=H}]' | wc -l
     227
% unichars '[\p{Ea=F}\p{Ea=H}\p{Ea=Na}]' | wc -l
     338
% unichars '[\p{Ea=F}\p{Ea=H}\p{Ea=Na}\pM]' | wc -l
    1488

Чтобы показать, сколько многих свойств эти вещи действительно имеют, вот полный дамп свойств трех разных символов, работающих с Unicode 5.2:

% uniprops -ga NEL "COMBINING TILDE" ff5e 
U+0085 ‹U+0085› \N{ NEXT LINE (NEL) }:
    \s \v \R \pC \p{Cc}
    All Any Assigned InLatin1 C Other Cc Cntrl Common Zyyy Control Pat_WS Pattern_White_Space PatWS Space SpacePerl VertSpace
       White_Space WSpace
    Age:1.1 Bidi_Class:B Bidi_Class=Paragraph_Separator Bidi_Class:Paragraph_Separator Bc=B Block:Latin_1
       Block=Latin_1_Supplement Block:Latin_1_Supplement Blk=Latin1 General_Category=Other Canonical_Combining_Class:0
       Canonical_Combining_Class=Not_Reordered Canonical_Combining_Class:Not_Reordered Ccc=NR Canonical_Combining_Class:NR
       General_Category=Control Script=Common Decomposition_Type:None Dt=None East_Asian_Width=Neutral East_Asian_Width:Neutral
       General_Category:C General_Category:Cc General_Category:Cntrl General_Category:Control Gc=Cc General_Category:Other Gc=C
       Grapheme_Cluster_Break:CN Grapheme_Cluster_Break=Control Grapheme_Cluster_Break:Control GCB=CN Hangul_Syllable_Type:NA
       Hangul_Syllable_Type=Not_Applicable Hangul_Syllable_Type:Not_Applicable Hst=NA Joining_Group:No_Joining_Group
       Jg=NoJoiningGroup Joining_Type:Non_Joining Jt=U Joining_Type:U Joining_Type=Non_Joining Line_Break:Next_Line Lb=NL
       Line_Break:NL Line_Break=Next_Line Numeric_Type:None Nt=None Numeric_Value:NaN Nv=NaN Present_In:1.1 Age=1.1 In=1.1
       Present_In:2.0 In=2.0 Present_In:2.1 In=2.1 Present_In:3.0 In=3.0 Present_In:3.1 In=3.1 Present_In:3.2 In=3.2
       Present_In:4.0 In=4.0 Present_In:4.1 In=4.1 Present_In:5.0 In=5.0 Present_In:5.1 In=5.1 Present_In:5.2 In=5.2
       Script:Common Sc=Zyyy Script:Zyyy Sentence_Break:SE Sentence_Break=Sep Sentence_Break:Sep SB=SE Word_Break:Newline WB=NL
       Word_Break:NL Word_Break=Newline
U+0303 ‹̃› \N{ COMBINING TILDE }:
    \w \pM \p{Mn}
    All Any Assigned InCombiningDiacriticalMarks Case_Ignorable CI Dia Diacritic M Mn Gr_Ext Grapheme_Extend Graph GrExt
       ID_Continue IDC Inherited Zinh Mark Nonspacing_Mark Print Qaai Word XID_Continue XIDC
    Age:1.1 Bidi_Class:Nonspacing_Mark Bc=NSM Bidi_Class:NSM Bidi_Class=Nonspacing_Mark Block:Combining_Diacritical_Marks
       Canonical_Combining_Class:230 Canonical_Combining_Class=Above Canonical_Combining_Class:A
       Canonical_Combining_Class:Above Ccc=A Decomposition_Type:None Dt=None East_Asian_Width:A East_Asian_Width=Ambiguous
       East_Asian_Width:Ambiguous Ea=A General_Category:M General_Category=Mark General_Category:Mark Gc=M General_Category:Mn
       General_Category=Nonspacing_Mark General_Category:Nonspacing_Mark Gc=Mn Grapheme_Cluster_Break:EX
       Grapheme_Cluster_Break=Extend Grapheme_Cluster_Break:Extend GCB=EX Hangul_Syllable_Type:NA
       Hangul_Syllable_Type=Not_Applicable Hangul_Syllable_Type:Not_Applicable Hst=NA Script=Inherited
       Joining_Group:No_Joining_Group Jg=NoJoiningGroup Joining_Type:T Joining_Type=Transparent Joining_Type:Transparent Jt=T
       Line_Break:CM Line_Break=Combining_Mark Line_Break:Combining_Mark Lb=CM NFC_Quick_Check:M NFC_Quick_Check=Maybe
       NFC_Quick_Check:Maybe NFCQC=M NFKC_Quick_Check:M NFKC_Quick_Check=Maybe NFKC_Quick_Check:Maybe NFKCQC=M
       Numeric_Type:None Nt=None Numeric_Value:NaN Nv=NaN Present_In:1.1 Age=1.1 In=1.1 Present_In:2.0 In=2.0 Present_In:2.1
       In=2.1 Present_In:3.0 In=3.0 Present_In:3.1 In=3.1 Present_In:3.2 In=3.2 Present_In:4.0 In=4.0 Present_In:4.1 In=4.1
       Present_In:5.0 In=5.0 Present_In:5.1 In=5.1 Present_In:5.2 In=5.2 Script:Inherited Sc=Zinh Script:Qaai Script:Zinh
       Sentence_Break:EX Sentence_Break=Extend Sentence_Break:Extend SB=EX Word_Break:Extend WB=Extend
U+FF5E ‹~› \N{ FULLWIDTH TILDE }:
    \pS \p{Sm}
    All Any Assigned InHalfwidthAndFullwidthForms Changes_When_NFKC_Casefolded CWKCF Common Zyyy Sm S Gr_Base Grapheme_Base
       Graph GrBase Math Math_Symbol Print Symbol
    Age:1.1 Bidi_Class:ON Bidi_Class=Other_Neutral Bidi_Class:Other_Neutral Bc=ON Block:Halfwidth_And_Fullwidth_Forms
       Canonical_Combining_Class:0 Canonical_Combining_Class=Not_Reordered Canonical_Combining_Class:Not_Reordered Ccc=NR
       Canonical_Combining_Class:NR Script=Common Decomposition_Type:Non_Canon Decomposition_Type=Non_Canonical
       Decomposition_Type:Non_Canonical Dt=NonCanon Decomposition_Type:Wide Dt=Wide East_Asian_Width:F
       East_Asian_Width=Fullwidth East_Asian_Width:Fullwidth Ea=F General_Category:Math_Symbol Gc=Sm General_Category:S
       General_Category=Symbol General_Category:Sm General_Category=Math_Symbol General_Category:Symbol Gc=S
       Grapheme_Cluster_Break:Other GCB=XX Grapheme_Cluster_Break:XX Grapheme_Cluster_Break=Other Hangul_Syllable_Type:NA
       Hangul_Syllable_Type=Not_Applicable Hangul_Syllable_Type:Not_Applicable Hst=NA Joining_Group:No_Joining_Group
       Jg=NoJoiningGroup Joining_Type:Non_Joining Jt=U Joining_Type:U Joining_Type=Non_Joining Line_Break:ID
       Line_Break=Ideographic Line_Break:Ideographic Lb=ID Numeric_Type:None Nt=None Numeric_Value:NaN Nv=NaN Present_In:1.1
       Age=1.1 In=1.1 Present_In:2.0 In=2.0 Present_In:2.1 In=2.1 Present_In:3.0 In=3.0 Present_In:3.1 In=3.1 Present_In:3.2
       In=3.2 Present_In:4.0 In=4.0 Present_In:4.1 In=4.1 Present_In:5.0 In=5.0 Present_In:5.1 In=5.1 Present_In:5.2 In=5.2
       Script:Common Sc=Zyyy Script:Zyyy Sentence_Break:Other SB=XX Sentence_Break:XX Sentence_Break=Other Word_Break:Other
       WB=XX Word_Break:XX Word_Break=Other

Довольно потрясающе, а?

Если вы читали это далеко и хотели бы знать, где взять три утилиты Unicode, показанные выше, uniprops, unichars и uninames, пожалуйста, пришлите мне письмо, потому что текущие ссылки не работает прямо сейчас.

2 голосов
/ 12 ноября 2010

Возможно, что-то из набора функций многобайтовой строки? http://php.net/manual/en/function.mb-ereg.php Не вижу mb_trim, но есть набор безопасных регулярных выражений в МБ.

G

1 голос
/ 12 ноября 2010
0 голосов
/ 25 марта 2014

однако здесь мое ЕДИНСТВЕННОЕ решение , потому что иногда есть пробелы UTF8:

$stringg = preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u','',$stringg);
$stringg = preg_replace('/\s+/u', '', $stringg);
...