اینترنت پنجره ها اندروید
بسط دادن

تعیین رمزگذاری متن در PHP - مروری بر راه حل های موجود، به علاوه دوچرخه دیگر. تعیین رمزگذاری متن در PHP - مروری بر راه حل های موجود به علاوه یک دوچرخه دیگر که صفحه Php را رمزگذاری می کند ویندوز 1251

با یک کار روبرو شد - شناسایی خودکار رمزگذاری صفحه / متن / هر چیزی. مشکل جدید نیست و دوچرخه های زیادی قبلاً اختراع شده اند. مقاله نمای کلی کوچکدر شبکه یافت شد - به علاوه یک پیشنهاد از خودم، به نظر من، یک راه حل ارزشمند.

1. چرا mb_detect_encoding () را انجام نمی دهید؟

خلاصه کار نمیکنه

بیا یک نگاهی بیندازیم:
// در ورودی - متن روسی با کد CP1251 $ string = iconv ("UTF-8"، "Windows-1251"، "او پیش آنا پاولونا رفت، دست او را بوسید و پچ طاس معطر و درخشان خود را جایگزین او کرد. و آرام روی مبل نشست. // بیایید ببینیم md_detect_encoding () چه چیزی به ما می دهد. اول $ strict = FALSE var_dump (mb_detect_encoding ($ string, array ("UTF-8"))); // UTF-8 var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "Windows-1251"))); // Windows-1251 var_dump (mb_detect_encoding ($ string، آرایه ("UTF-8"، "KOI8-R"))); // KOI8-R var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "Windows-1251"، "KOI8-R"))); // FALSE var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "ISO-8859-5"))); // ISO-8859-5 var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "Windows-1251"، "KOI8-R"، "ISO-8859-5"))); // ISO-8859-5 // اکنون $ strict = TRUE var_dump (mb_detect_encoding ($ string, array ("UTF-8"), TRUE)); // FALSE var_dump (mb_detect_encoding ($ string، آرایه ("UTF-8"، "Windows-1251")، TRUE)); // FALSE var_dump (mb_detect_encoding ($ string، آرایه ("UTF-8"، "KOI8-R")، TRUE)); // FALSE var_dump (mb_detect_encoding ($ string، آرایه ("UTF-8"، "Windows-1251"، "KOI8-R")، TRUE)); // FALSE var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "ISO-8859-5")، TRUE)); // ISO-8859-5 var_dump (mb_detect_encoding (رشته $، آرایه ("UTF-8"، "Windows-1251"، "KOI8-R"، "ISO-8859-5")، TRUE)); // ISO-8859-5
همانطور که می بینید، خروجی یک آشفتگی کامل است. وقتی مشخص نیست چرا یک تابع اینگونه رفتار می کند، چه کار می کنیم؟ درست است، ما در گوگل جستجو می کنیم. یک پاسخ عالی پیدا کرد.

برای از بین بردن تمام امیدها برای استفاده از mb_detect_encoding ()، باید وارد کد منبع پسوند mbstring شوید. بنابراین، آستین‌ها را بالا زدیم، بریم:
// ext / mbstring / mbstring.c: 2629 PHP_FUNCTION (mb_detect_encoding) (... // line 2703 ret = mbfl_identify_encoding_name (& string, elist, size, strict);...
Ctrl + کلیک کنید:
// ext / mbstring / libmbfl / mbfl / mbfilter.c: 643 const char * mbfl_identify_encoding_name (mbfl_string * string, enum mbfl_no_encoding * elist, int elistsz, int strict) (const mbfl_encoding .string_encoding = encoding ; ..
Ctrl + کلیک کنید:
// ext / mbstring / libmbfl / mbfl / mbfilter.c: 557 / * * شناسایی رمزگذاری * / const mbfl_encoding * mbfl_identify_encoding (mbfl_string * string, enum mbfl_no_encoding * elist, int elistsz, int strict) (...
من متن کامل روش را پست نمی کنم تا مقاله را با منابع غیر ضروری پر نکنم. کسانی که علاقه مند به دیدن آن برای خود هستند. ما از خط شماره 593 عذاب می‌شویم، جایی که در واقع بررسی می‌شود که آیا کاراکتر برای رمزگذاری مناسب است یا خیر:
// ext / mbstring / libmbfl / mbfl / mbfilter.c: 593 (* filter-> filter_function) (* p, filter); if (filter-> flag) (بد ++;)
در اینجا فیلترهای اصلی برای سیریلیک تک بایتی آمده است:

Windows-1251 (نظرات اصلی حفظ شده است)
// ext / mbstring / libmbfl / filters / mbfilter_cp1251.c: 142 / * همه اینها اکنون بسیار زشت است! * / static int mbfl_filt_ident_cp1251 (int c, mbfl_identify_filter * filter) (اگر (c> = 0x80 && c< 0xff) filter->پرچم = 0; else filter->

KOI8-R
// ext / mbstring / libmbfl / filters / mbfilter_koi8r.c: 142 static int mbfl_filt_ident_koi8r (int c, mbfl_identify_filter * filter) (اگر (c> = 0x80 && c< 0xff) filter->پرچم = 0; else filter-> flag = 1; / * نه آن * / بازگشت c; )

ISO-8859-5 (اینجا همه چیز سرگرم کننده است)
// ext / mbstring / libmbfl / mbfl / mbfl_ident.c: 248 int mbfl_filt_ident_true (int c، mbfl_identify_filter * filter) (return c;)
همانطور که می بینید، ISO-8859-5 همیشه TRUE را برمی گرداند (برای برگرداندن FALSE، باید filter-> flag = 1 را تنظیم کنید).

وقتی به فیلترها نگاه کردیم همه چیز سر جای خودش قرار گرفت. CP1251 از KOI8-R قابل تشخیص نیست. اگر ISO-8859-5 در لیست کدگذاری ها باشد، همیشه صحیح تشخیص داده می شود.

به طور کلی، شکست بخورید. قابل درک است - فقط با کدهای کاراکتر نمی توان رمزگذاری را در حالت کلی پیدا کرد، زیرا این کدها در کدگذاری های مختلف متقاطع می شوند.

2. آنچه گوگل ارائه می دهد

و گوگل انواع و اقسام افتضاح را به نمایش می گذارد. من حتی منابع را اینجا قرار نمی دهم، اگر خواستید خودتان نگاهی بیندازید (فاصله بعد از http: // را بردارید، من نمی دانم چگونه متن را بدون لینک نشان دهم):

Http: // deer.org.ua/2009/10/06/1/
http: // php.su/forum/topic.php?forum=1&topic=1346

3. جستجو بر اساس habr

1) دوباره کدهای کاراکتر: habrahabr.ru/blogs/php/27378/#comment_710532

2) به نظر من یک راه حل بسیار جالب: habrahabr.ru/blogs/php/27378/#comment_1399654
معایب و مزایا در نظر روی لینک. شخصاً فکر می کنم که این راه حل فقط برای تشخیص رمزگذاری اضافی است - خیلی قدرتمند به نظر می رسد. تعیین رمزگذاری در آن یک عارضه جانبی است).

4. در واقع، تصمیم من است

این ایده با نگاه کردن به لینک دوم از بخش قبل مطرح شد. ایده به شرح زیر است: ما یک متن بزرگ روسی می گیریم، فرکانس حروف مختلف را اندازه گیری می کنیم و از این فرکانس ها برای شناسایی رمزگذاری استفاده می کنیم. با نگاهی به آینده، فوراً می گویم که با حروف بزرگ و کوچک مشکلاتی پیش خواهد آمد. بنابراین، من نمونه‌هایی از بسامدهای حروف (بیایید آن را "طیف" بنامیم) ارسال می‌کنم، هم به بزرگی و هم به بزرگی کوچک و بزرگ (در مورد دوم، یک حرف بزرگ‌تر به حرف کوچک با همان فرکانس اضافه کردم و همه موارد را حذف کردم. بزرگ). در این "طیف ها" همه حروف با فرکانس کمتر از 0.001 و یک فاصله قطع می شوند. این چیزی است که پس از ویرایش جنگ و صلح به دست آوردم:

"طیف" حساس به حروف کوچک و بزرگ:
آرایه ( "O" => .095249209893009، "E" => 0.06836817536026، "یک" => .067481298384992، "تو" => .055995027400041، "N" => .052242744063325، .... "و" => .002252892226507، "H "=> .0021318391371162،" P "=> .0018574762967903،" F "=> .0015961610948418،" B "=> .0014044332975731،" O "=> .0013188987793209،" A "=> .0012623590130186،" K "=>" 0.001180 => .001061932790165 ،)

مورد غیر حساس:
آرایه ( "O" => .095249209893009، "O" => .095249209893009، "E" => 0.06836817536026، "E" => 0.06836817536026، "A" => .067481298384992، "یک" => .067481298384992، "من" => 0.0559950274000 "، و" => .055995027400041، .... "C" => .0029893589260344، "ج" => .0029893589260344، "تو" => .0024649163501406، "U" => .0024649163501406، "E" => .002252892226507، "E" => 0.002252892226507، "F" => 0.0015961610948418، "f" => 0.0015961610948418،)

طیف در کدگذاری های مختلف (کلیدهای آرایه کدهای کاراکترهای مربوطه در رمزگذاری مربوطه هستند):

به علاوه. ما یک متن از یک رمزگذاری ناشناخته را می گیریم، برای هر کدگذاری آزمایش شده، فرکانس کاراکتر فعلی را پیدا می کنیم و آن را به "رتبه بندی" این رمزگذاری اضافه می کنیم. رمزگذاری با رتبه بالاتر، به احتمال زیاد، رمزگذاری متن است.

$ encodings = آرایه ("cp1251" => نیاز به "specter_cp1251.php"، "koi8r" => نیاز به "specter_koi8r.php"، "iso88595" => نیاز به "specter_iso88595.php"); $ enc_rates = آرایه (); برای ($ i = 0؛ $ i< len($str); ++$i) { foreach ($encodings as $encoding =>$ char_specter) ($ enc_rates [$ encoding] + = $ char_specter)]; )) var_dump ($ enc_rates)؛
حتی سعی نکنید این کد را به تنهایی اجرا کنید - کار نخواهد کرد. شما می توانید این را به عنوان شبه کد در نظر بگیرید - من جزئیات را حذف کردم تا مقاله را به هم نریزم. $ char_specter دقیقاً آرایه هایی هستند که توسط pastebin به آنها ارجاع داده شده است.

نتایج
ردیف‌های جدول کدگذاری متن هستند، ستون‌ها محتوای آرایه $ enc_rates هستند.

1) $ str = "متن روسی";
0.441 | 0.020 | 0.085 | Windows-1251
0.049 | 0.441 | 0.166 | KOI8-R
0.133 | 0.092 | 0.441 | ISO-8859-5

همه کاملا. رمزگذاری واقعی در حال حاضر دارای امتیاز 4 برابر بالاتر از سایرین است - این برای چنین متن کوتاهی است. در متون طولانی تر، این نسبت تقریباً یکسان خواهد بود.


cp1251 | koi8r | iso88595 |
0.013 | 0.705 | 0.331 | Windows-1251
0.649 | 0.013 | 0.201 | KOI8-R
0.007 | 0.392 | 0.013 | ISO-8859-5

اوه! فرنی کامل. اما چون حروف بزرگ در CP1251 معمولاً با حروف کوچک در KOI8-R مطابقت دارد. و حروف کوچک به نوبه خود بسیار بیشتر از حروف بزرگ استفاده می شوند. بنابراین رشته با کلاه در CP1251 را به صورت KOI8-R تعریف می کنیم.
ما سعی می کنیم بدون توجه به حروف کوچک و بزرگ این کار را انجام دهیم (طیف های حساس به حروف کوچک و بزرگ)

1) $ str = "متن روسی";
cp1251 | koi8r | iso88595 |
0.477 | 0.342 | 0.085 | Windows-1251
0.315 | 0.477 | 0.207 | KOI8-R
0.216 | 0.321 | 0.477 | ISO-8859-5

2) $ str = "LINE CAPPY RUSSIAN TEXT";
cp1251 | koi8r | iso88595 |
1.074 | 0.705 | 0.465 | Windows-1251
0.649 | 1.074 | 0.201 | KOI8-R
0.331 | 0.392 | 1.074 | ISO-8859-5

همانطور که می بینید، رمزگذاری صحیح نیز به طور مداوم با "طیف" حساس به حروف بزرگ پیشرو است (اگر رشته حاوی مقدار کمی باشد. حروف بزرگ) و به حروف بزرگ و کوچک حساس نیست. در مورد دوم، با موارد حساس به حروف بزرگ، البته رهبر چندان مطمئن نیست، اما حتی در خطوط کوچک کاملاً پایدار است. شما همچنین می توانید با وزن حروف بازی کنید - برای مثال آنها را با توجه به فرکانس غیرخطی کنید.

5. نتیجه گیری

موضوع کار با UTF-8 را پوشش نمی دهد - هیچ تفاوت اساسی در اینجا وجود ندارد، به جز اینکه دریافت کدهای کاراکتر و تقسیم یک رشته به کاراکترها کمی طولانی تر / پیچیده تر خواهد بود.
البته می توان این ایده ها را نه تنها به رمزگذاری های سیریلیک گسترش داد - تنها سوال در "طیف" زبان ها / رمزگذاری های مربوطه است.

P.S. اگر بسیار ضروری / جالب باشد - قسمت دوم کتابخانه کاملاً فعال را در GitHub ارسال خواهم کرد. اگرچه من معتقدم که داده های موجود در پست برای نوشتن سریع چنین کتابخانه ای و مطابق با نیازهای شما کاملاً کافی است - "طیف" برای زبان روسی گذاشته شده است ، می توان آن را به راحتی به تمام رمزگذاری های لازم منتقل کرد.

بیایید به صفحه HTML خود که در درس های قبلی ایجاد کرده بودیم برگردیم و اکنون رمزگذاری را تنظیم می کنیم که متن آن در آن ذخیره شود.

من می خواهم در مورد دو روش به شما بگویم که چگونه می توانید رمزگذاری متن را تغییر دهید. به عنوان یک قاعده، من از آنها در عمل استفاده می کنم و آنها خود را به خوبی ثابت کرده اند.

مطمئن ترین راه برای تغییر رمزگذاری متن، این است برنامه های Notepad++. به عنوان یک قاعده، این روش همیشه قابل اعتماد کار می کند و با کمک آن می توانید سخت ترین مشکلات را حل کنید.

1 راه. با استفاده از Notepad ++

بنابراین، برای تغییر رمزگذاری متن، ما نیاز به یک ویژه داریم ویرایشگر متن notepad ++ نامیده می شود.

این برنامه رایگان است و می توانید آن را از این سایت دانلود کنید:

با استفاده از این برنامه یک صفحه HTML باز کنید و به منوی اصلی "Encodings" بروید.

رمزگذاری را که می خواهید به آن تبدیل کنید انتخاب کنید و فایل را ذخیره کنید.

این کل روال است. برنامه بسیار خوبی است و بر خلاف سایر گزینه ها، کدگذاری را بدون نقص تغییر می دهد.

روش 2. با ویرایشگر کد همه منظوره Dreamweaver.

اگر در ویرایشگر کد جهانی Dreamweaver کار می کنید، گزینه ای برای تعیین رمزگذاری که در آن متن ارائه می شود نیز وجود دارد.


این را می توان با استفاده از منوی اصلی "تغییر - ویژگی های صفحه" نیز انجام داد.


علاوه بر این، در دسته "نام / رمزگذاری" رمزگذاری مورد نیاز خود را انتخاب کنید. بیشتر اوقات رمزگذاری یونیکد (UTF-8) خواهد بود.

هنگام ایجاد یک سند html جدید، این روش به خوبی کار می کند، اما اگر رمزگذاری یک فایل موجود را تغییر دهید، بهتر است از روش اول استفاده کنید. در این صورت بهتر عمل می کند.

این عملیات را روی کامپیوتر خود انجام دهید.

اما، مشخص کردن کدگذاری متن برای صفحه html هنوز کافی نیست. برای عملکرد عادی آن، باید یک اقدام دیگر انجام دهید: به مرورگر بگویید متن با چه رمزگذاری نوشته شده است.

یک اسکریپت ساده ناگهان از کار افتاد. وظیفه اسکریپت دریافت یک صفحه HTML (از یک بازی مرورگر) و واکشی داده ها با استفاده از عبارات منظم است. به عنوان یک مبتدی، این رویداد باعث سردرگمی و وحشت جزئی برای من شد: بالاخره دیروز همه چیز درست شد! موضوع چیه؟
من باید به طور کامل درک می کردم که برخی از توابع PHP چگونه کار می کنند.

کد بسیار ابتدایی بود:

الگوی $ =; $ URL = "http://www.heroeswm.ru/pl_info.php?id=($id)"; $ html = file_get_contents ($ url); preg_match ($ الگو، $ html، $ matches)؛ if (isset ($ مطابق [1])) echo $ مطابق [1]; else echo "یافت نشد"؛

$ pattern = "# یک حرف بنویسید (. *) سطح نبرد # است"; $ url = "http://www.heroeswm.ru/pl_info.php?id=($id)"؛ $ html = file_get_contents ($ url); preg_match ($ الگو، $ html، $ matches)؛ if (isset ($ مطابقت)) echo $ مطابقت دارد. else echo "یافت نشد"؛

بازیابی داده ها و تجزیه آنها با استفاده از یک عبارت منظم ساده.
باید بگویم که این کد نتیجه یک تغییر جزئی است. در نسخه اصلی، جستجوی معمولی بر اساس تگ های HTML بود. اما من نیاز داشتم بین دو عبارت روسی قطعه ای پیدا کنم. من کلمات روسی را به قالب جستجو اضافه کردم و این تغییر بود که حیاتی شد.

و حالا به ترتیب
سایت بازی www.heroeswm.ru صفحاتی را در رمزگذاری ارائه می دهد win-1251... من یک کدگذاری روی سرور دارم UTF-8، بنابراین همه اسکریپت ها در هستند UTF-8بدون BOM
اسکریپت اصلی با جستجو بر اساس تگ های HTML، با وجود تفاوت در رمزگذاری، به درستی کار می کرد، اما وقتی کاراکترهای سیریلیک را به قالب جستجو اضافه کردم، جستجو و یافتن را متوقف کردم. در وظیفه من، رد کردن مشکل و انتخاب الگوی دیگری - بدون کلمات روسی - بسیار آسان است، اما در بیشتر موارد این غیرممکن است. بنابراین، تصمیم گرفتم آن را به طور کامل کشف کنم: تفاوت اساسی بین رمزگذاری ها چیست؟چرا داره زنگ میزنه کار نادرست عبارات منظم، و در همان زمان - چه عملکردهایی تحت تأثیر قرار می گیرندبه دلیل تفاوت در رمزگذاری ها، و نحوه دور زدن آن.

برای بدست آوردن داده ها از تابع file_get_contents () استفاده کردم که دستور زیر را دارد:

رشته file_get_contents ( رشته$ filename)، که در آن $ filename نام فایلی است که باید خوانده شود.
در صورت عدم دریافت داده، یک رشته یا bool (نادرست) را برمی گرداند.

واضح ترین تفاوت بین رمزگذاری ها win-1251و UTF-8تعداد کاراکترهایی است که می توان با آنها کدگذاری کرد. اولین (و سایر موارد مشابه) فقط به 255 بستگی دارد، زیرا هر کاراکتر در یک بایت رمزگذاری شده است.

با کمک دوم، می توانید مجموعه ای واقعاً عظیم از شخصیت ها، از جمله حروف الفبای ملی، حروف عربی و هیروگلیف را منتقل کنید. چنین گسترشی از مجموعه کاراکترها به این دلیل حاصل می شود که کاراکترها نه با یک، بلکه با دو (برای اکثر کاراکترها) و بیشتر (تا چهار) بایت کدگذاری می شوند. بنابراین رمزگذاری UTF-8(و مانند آن) را چند بایتی یا چند بایتی می گویند در مقابل تک بایتی مانند win-1251.

با چنین مجموعه گسترده ای از نشانه ها، UTF-8نه تنها اجازه استفاده از حروف الفبای مختلف را در یک سایت می دهد، بلکه تضمین می کند که سایت روسی زبان به درستی نمایش داده می شود حتی در صورت وجود رمزگذاری با پشتیبانی سیریلیک ( win-1251, KOI8-R, CP866, ISO 8859-5و دیگران) حتی مشکوک نیستند: در ژاپن، کره، کشورهای عربی و غیره. پرداخت برای چنین تطبیق پذیری وزن کمی بیشتر از کاراکترها در طول ذخیره سازی و بر این اساس، زمان پردازش طولانی تر برای توابع رشته خواهد بود. PHP... به هر حال، آنها در بیشتر موارد به درستی کار نخواهند کرد. این دقیقاً همان مشکلی است که من با آن برخورد کردم: regex اسکریپت نوشته شده در آن UTF-8، من فقط نتوانستم زیررشته صحیح مورد نیاز خود، از جمله نویسه های سیریلیک را در صفحه دریافتی از سایت در پیدا کنم. Windows-1251.

منطقی است که فرض کنیم سایت هایی که فقط از حروف سیریلیک و لاتین استفاده می کنند، این کار را می کنند UTF-8به هیچ، و تجزیه کننده ساده مورد بررسی به خوبی در آن "زندگی" کرد win-1251، اما شرایطی وجود دارد که از نیاز به دوستی با این رمزگذاری ها و استفاده می شود توابع رشته PHPبه عنوان مثال، هنگام توسعه یک پروژه، فقط بیرون نروید UTF-8.

چه چیزی باعث رفتار نادرست توابع رشته شده است؟

همانطور که قبلا ذکر شد، تفاوت اصلی بین رمزگذاری ها طول کاراکترها است. بنابراین، هنگام استفاده از توابعی که در آنها با کاراکترها مانند بایت کار می کنند، مشکلاتی ایجاد می شود و مقادیر را در بایت نیز برمی گرداند (برای رمزگذاری تک بایتی، این درست است: یک کاراکتر برابر با یک بایت است).

به عنوان مثال، تابع

substr ("بررسی"، 0، 5)؛ // متن در رمزگذاری UTF-8

substr ("بررسی"، 0، 5)؛ // متن در رمزگذاری UTF-8

به جای «اثبات» مورد انتظار، «Pr�» را برمی‌گرداند: در UTF-8کاراکترهای سیریلیک در دو بایت کدگذاری می شوند، در نتیجه ما "krakozyabr" - تنها بایت اول کاراکتر "o" را می بینیم.

بنابراین، در بیشتر موارد، برای کار با رشته ها در UTF-8به استفاده از توابع خاص نیاز دارد (به عنوان مثال، از پسوند پی اچ پی mbstring، و گاهی اوقات استفاده از هر دو (مثلاً برای انتقال اندازه یک رشته در بایت به هدر HTTP، باید strlen () را ترک کنید، و برای شمارش تعداد کاراکترها، باید mb_strlen را اضافه کنید ( )).

نحو توابع پر استفاده که ممکن است نیاز به جایگزینی با توابع از یک برنامه افزودنی داشته باشد پی اچ پی mbString:

بین المللی strlen ( رشتهرشته $) - طول رشته یا 0 را در صورت خالی بودن رشته برمی گرداند.

بین المللی strpos ( رشته$ انبار کاه، مختلطسوزن $) - موقعیت اولین وقوع رشته $ سوزن را در زیر رشته $ haystack برمی گرداند، یا نادرستاگر پیدا نشد

stripos مشابه عملکرد قبلی است، فقط جستجو به حروف بزرگ و کوچک حساس نیست.

رشتهزیر خیابان ( رشتهرشته $، بین المللیشروع $ [، int $ طول]) - به شما امکان می دهد یک رشته فرعی را از موقعیت کاراکتر مشخص شده شروع کنید و هنگام تعیین پارامتر سوم، طول مشخصی را انتخاب کنید.

همتایان آنها برای کار در رمزگذاری های چند بایتی طراحی شده اند: mb_strlen، mb_strpos، mb_stripos و mb_substr.

البته توابع بسیار بیشتری برای کار با متن وجود دارد. من فقط محبوب ترین آنها را لیست کرده ام.

توابع کار با عبارات منظم، طراحی شده برای یافتن یک زیر رشته (رشته های فرعی) که با ماسک ارائه شده توسط عبارت منظم مطابقت دارد، از هم جدا هستند.

بین المللی preg_match ( رشتهالگوی $، رشتهموضوع $، آرایهو $ منطبق)

بین المللی preg_match_all ( رشتهالگوی $، رشتهموضوع $ آرایه& $ مطابقت دارد).

متن موضوع $ برای مطابقت با الگوی عبارت منظم $ جستجو می شود. نتیجه جستجو در متغیر $ matches نوشته می شود. تابع تعداد موارد منطبق با الگو را برمی گرداند، در صورت بروز خطا، باز خواهد گشت نادرست.

برای استفاده از رمزگذاری های چند بایتی برای تطبیق الگو عبارات با قاعده، باید اصلاح کننده / u را به آنها اضافه کنید یا از گروه تابع mb_ereg * استفاده کنید.

چه باید کرد؟

اولین راه حل این است که دوباره کدگذاری کنید UTF-8دریافت شده در win-1251داده - ناخوشایند به نظر می رسید. از این گذشته ، پس از رمزگذاری مجدد ، تمام عملکردهای معمول باید با موارد خاصی برای کار با آنها جایگزین شوند. UTF-8، یا سعی کنید از اصلاح کننده / u استفاده کنید (با نگاهی به آینده، می گویم که به شما امکان می دهد با رشته ها در رمزگذاری های تک بایتی کار کنید، "مانند رشته ها UTF-8"، اما برای خطوط در معتبر نیست UTF-8). در مثال من، فقط یک preg_match () وجود دارد، اما در عمل به ندرت چنین است.

بنابراین، من کار را "معکوس" می کنم: می خواهم از توابع معمول preg_match () استفاده کنم، و برای این کار نه رشته ورودی، بلکه الگوی جستجو را با استفاده از iconv () دوباره کد می کنم.

نحو توابع:
رشته iconv ($ in_charset، $ out_charset، $ str) - $ str را از $ in_charset به $ out_charset تبدیل می‌کند. متن رمزگذاری شده را بدون تأثیر بر متغیر اصلی برمی‌گرداند.

عملکرد رشته ای را در رمزگذاری جدید برمی گردانداما رمزگذاری خود رشته را تغییر نمی دهد. از همین رو

$ pattern = "# یک حرف بنویسید (. *) سطح نبرد # است"; iconv ("UTF-8"، "WINDOWS-1251"، الگوی $)؛ // الگوی $ در preg_match اصلی باقی می ماند ($ pattern, $ html, $ matches);

کار نمی کند - الگوی $ در رمزگذاری اصلی باقی می ماند UTF-8... شما باید نتیجه iconv را به یک متغیر اختصاص دهید:

الگوی دلار = "# یک حرف بنویسید (. *) سطح نبرد # است"; $ pattern = iconv ("UTF-8"، "WINDOWS-1251"، $ pattern); preg_match ($ الگو، $ html، $ matches)؛

$ pattern = "# یک حرف بنویسید (. *) سطح نبرد # است"; $ pattern = iconv ("UTF-8"، "WINDOWS-1251"، $ pattern); preg_match ($ الگو، $ html، $ matches)؛

اکنون جستجو به درستی کار می کند، اما فقط مرورگر krakozyabry جامد را ارسال می کند. خوب، در اینجا من قبلاً می دانم که چه کاری باید انجام دهم: شما باید نتیجه را در یک رمزگذاری کاری مجدد کدگذاری کنید UTF-8... و سپس نکته دوم ظاهر شد ، که برای من واضح نبود ، اگرچه اگر تجربه بیشتری داشتم ، احتمالاً هیچ مشکلی ایجاد نمی کردم: چرا iconv () برخی از متغیرها را مجدداً کد می کند و برخی دیگر را نه؟

متغیر $ matches یک آرایه است، و من سعی کردم با یک رمزگذاری مجدد iconv ($ matches) خلاص شوم. یک بار دیگر، من به شرح نحو توابع نگاه می کنم: خوب، البته، همه پارامترها باید رشته باشند، نه آرایه. یعنی باید روی تمام مقادیر آرایه ای که نیاز به رمزگذاری مجدد دارند تکرار شود و آنها را به رمزگذاری مورد نظر... در مثالم، من روی آرایه تکرار نکردم، زیرا به یک مقدار علاقه مند بودم و نه کل آرایه. من همچنین آن را به عنوان پارامتر تابع iconv () مشخص کردم.

این چیزی است که من در نسخه نهایی دریافت کردم:

// کدگذاری پیش فرض را تنظیم کنید setlocale (LC_ALL، "ru_RU.UTF-8")؛ سرتیتر ( "نوع محتوا: متن / html؛ مجموعه حروف = UTF-8") الگوی دلار = "# یک حرف بنویسید (. *) سطح نبرد # است"; $ pattern = iconv ("UTF-8"، "WINDOWS-1251"، $ pattern); $ URL = "http://www.heroeswm.ru/pl_info.php?id=993353"; $ html = file_get_contents ($ url); preg_match ($ الگو، $ html، $ matches)؛ if (isset ($ matches [1])) echo $ matches [1] = iconv ("WINDOWS-1251"، "UTF-8"، $ مطابق [1]); else echo "یافت نشد"؛ ?>

مقاله توسط یکی از دوستان خوبم نوشته شده است. او به نوشتن و بررسی متون مشغول است، برنامه نویسی در PHP بیشتر سرگرمی او است. در وبلاگ من، او همه انتشارات را تصحیح می کند و این یکی هدیه او برای دومین سالگرد وبلاگ به من شد.

هیچ نشریه مشابهی یافت نشد.