Пишу, по большей части, про историю, свою жизнь и немного про программирование.

PHP, UTF-8, рассуждения по поводу строк

Тёмная материя (18.16КиБ)

Работаю с низким приоритетом над автоматической заменой операций получения символа в строке по индексу на такую же операцию, но которая умела бы работать с UTF-8. Оказалось, что задача очень сложная.

Во-первых, нужно учесть, что в PHP для способа получить символ по индексу — это квадратные скобки (\$str[0]) и фигурные ($str{0}). Причём, если мы встречаем фигурные скобки, то это точно строка, если мы встречаем фигурные, это может быть массив. Различать массив и строку в контексте абстрактных квадратных скобок, без полной интерпретации, невозможно. К счастью, мне это и не нужно, мой статический метод (я его назвал UTF::get(…)), проверяет является ли аргумент массивом и, если да, работает с ним как с массивом.

Во-вторых, если мы выделили какое-то выражение, а оно стоит слева от равно, то надо его пропустить — это присваивание и это с очень большой вероятностью массив. За все годы работы с PHP даже в самом кошмарном коде я встречал исчезающе мало присваиваний символа по индексу.

В-третьих, индексы могут идти подряд, например, $arr[0][2]{3}. Надо не забывать об этом и брать выражение целиком.

В-четвёртых, внутри индекса может идти любое годное PHP выражение, в том числе, внутри так же может быть операция взятия символа по индексу. Например: $str[1 + $str[0] + sin($arr[$a])].

В-пятых, есть переменные переменные, к примеру: $$$$$var[1], их тоже надо уметь обрабатывать, кроме того, они могут быть взяты в фигурные скобки, а в скобках могут быть вызовы функций, методов, имена переменных: ${$$$$var[1]}, ${$this->my()}{1}, ${str}{0}.

В-шестых, в PHP в строках опеределённого типа (в кавычках и heredoc) переменные интерполируются, в том числе интерполируются строковые переменные с получением символа по индексу, а кроме этого эти переменные могут быть в фигурных скобках: «{$aaa[1]} и можно ещё так: ${aaa[1]}», тут же надо не забывать, что переменные могут экранироваться, вот так: «\${aaa[1]}».

В общем, задача сложная, я над ней думаю. Пока в сторону парсеров синтаксиса (colorer, Text_Highlighter и PHP tokinizer). Из исследования выяснилось, что все они могут мне помочь примерно в равной степени, так что я думаю, что возьму PHP tokinizer.

К сожалению, ни один из парсеров не парсит PHP настолько удобно, чтобы избавить меня от всех проблем, так что я думаю над их решением. Когда у меня будет понимание как бороться со всеми проблемами, буду программировать.

5 комментариев
nudnik.ru 2010

На что только люди ни пойдут, чтобы KOI8-R не использовать.

brainstorm.name 2010

http://ru.php.net/mb_substr самое простое. если чтото быстрое делать то делать класс строки с хранением всех ее утф символов раздельно.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для brainstorm.name:

Тут речь идёт не о том на что заменять, а о том что заменять и по каким правилам. Прочитайте заметку-то.

Сергей 2010

Вопрос от PHP-нуба.
А почему в ПХП (по вашим словам) так редко встречается присваивание символа по индексу? Это связано с какими-то накладными расходами или что-то другое? Не могу придумать ни одной причины, потому, что всю жизнь работал почти исключительно с компилируемыми языками и в них эта операция вполне нормальна и весьма «дешева» в смысле накладных расходов.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для Сергей:

Это связано с какими-то накладными расходами или что-то другое?

Это связано с тем, что такие задачи вообще редко встречаются. Задача установить вместо одного символа другой очень широкая, если смотреть частные случаи, то они, обычно, решаются какими-то функциями (например, str_replace), коих в PHP великое множество.