PDA

View Full Version : سوال: درخواست کد regular expression (جدا کردن رشته بر اساس قواعدی در رشته دیگر)



abolfazl-z
جمعه 14 تیر 1392, 12:08 عصر
سلام دوستان:لبخندساده:

دوستان من کدی می خواستم که چند کار را برایم انجام دهد.
دوستان ما دو رشته داریم بصورت زیر :

salam[id]khoobiii[name]chetorii
salam1khoobiiiALIchetorii

خوب من کدی می خواهم که ابتدا رشته های داخل [] را به من بدهد سپس نسبت به مکان رشته اول ، رشته دوم رو به ما بدهد :

یعنی :
id => 1
name => ALI
دوستان میتونم برنامه اش رو بنویسم ولی رگولار سرعت بهتری دارد.

abolfazl-z
جمعه 14 تیر 1392, 22:11 عصر
خیلی سخت هست ؟ :متفکر:

MMSHFE
جمعه 14 تیر 1392, 23:09 عصر
راستش هر کاری کردم، ایده ای برای استفاده از RegEx به ذهنم نرسید. البته حقیقتش خیلی ذهنم درگیر یک پروژه است که دارم روش کار میکنم ولی بهرحال، این کدی که نوشتم، درست کار میکنه:


$t = 'salam[id]khoobiii[name]chetorii';
$s = 'salam1khoobiiiALIchetorii';
function GetKeys($template, $string) {
$strParts = array();
$start = 0;
$keys = array();
if(preg_match_all('#\[(.*?)\]#', $template, $keys)) {
$keys = $keys[1];
foreach($keys as $index => $key) {
$keys[$index] = '[' . $key . ']';
}
}
foreach($keys as $key) {
$strParts[] = substr($template, $start, strpos($template, $key) - $start);
$start = strpos($template, $key) + strlen($key);
}
$strParts[] = substr($template, $start);
$found = array();
$count = count($strParts);
for($i = 1; $i < $count; $i++) {
$start = strpos($string, $strParts[$i - 1]) + strlen($strParts[$i - 1]);
$end = strpos($string, $strParts[$i]) - $start;
$found[] = substr($string, $start, $end);
}
return $found;
}
print_r(GetKeys($t, $s));

abolfazl-z
شنبه 15 تیر 1392, 09:44 صبح
مرسی آقای شهرکی
ولی خودتون میدونید که این حالت فقط برای یک نوع داده کار می کند و برای حالت های دیگر خیر ولی من رویش کار می کنم بینم میتونم تکمیل اش کنم.
باز هم ممنونم.

MMSHFE
شنبه 15 تیر 1392, 10:28 صبح
یعنی چی برای یک نوع داده؟ این حالت تمام کلیدهایی که توی [] هستن رو استخراج و مقدارشون رو از توی رشته پیدا میکنه. حالا باز چک میکنم ببینم کد بهتری میتونم بنویسم یا نه.

MMSHFE
شنبه 15 تیر 1392, 10:33 صبح
$t = 'salam[id]khoobiii[name]chetorii';
$s = 'salam1khoobiiiALIchetorii';
function GetKeys($template, $string) {
$found = array();
if(preg_match_all('#\[(.*?)\]#', $template, $keys)) {
$strParts = array();
$start = 0;
$keys = array();
$keys = $keys[1];
foreach($keys as $key) {
$template = str_replace('[' . $key . ']', '[]', $template);
}
$strParts = explode('[]', $template);
$count = count($strParts);
for($i = 1; $i < $count; $i++) {
$start = strpos($string, $strParts[$i - 1]) + strlen($strParts[$i - 1]);
$end = strpos($string, $strParts[$i]) - $start;
$found[$keys[$i - 1]] = substr($string, $start, $end);
}
}
return $found;
}
print_r(GetKeys($t, $s));

این کد یکم بهینه شده و اندیس هر مقدار رو هم میده.

SONITAJ
شنبه 15 تیر 1392, 10:34 صبح
سلام
ببخشید استاد این کد روی حروف فارسی هم جواب میده؟یانه فقط حروف انگلیسی؟من هم یه چنین کدی را برای فرم سفارش وچک کردن متن های ورودی نیاز دارم؟
ممنون

MMSHFE
شنبه 15 تیر 1392, 10:40 صبح
باید جواب بده. البته اگه کار نکرد، بعد از # آخر رشته توی دستور preg_match_all حرف u رو بنویسید.

abolfazl-z
شنبه 15 تیر 1392, 12:22 عصر
$t = 'salam[id]khoobiii[name]chetorii';
$s = 'salam1khoobiiiALIchetorii';
function GetKeys($template, $string) {
$found = array();
if(preg_match_all('#\[(.*?)\]#', $template, $keys)) {
$strParts = array();
$start = 0;
$keys = array();
$keys = $keys[1];
foreach($keys as $key) {
$template = str_replace('[' . $key . ']', '[]', $template);
}
$strParts = explode('[]', $template);
$count = count($strParts);
for($i = 1; $i < $count; $i++) {
$start = strpos($string, $strParts[$i - 1]) + strlen($strParts[$i - 1]);
$end = strpos($string, $strParts[$i]) - $start;
$found[$keys[$i - 1]] = substr($string, $start, $end);
}
}
return $found;
}
print_r(GetKeys($t, $s));

این کد یکم بهینه شده و اندیس هر مقدار رو هم میده.

خطا میده :

Notice: Undefined offset: 1 in C:\xampp\htdocs\test2.php on line 10

Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\test2.php on line 11
Array ( )

-------------------------------------------------------------------------------------------


یعنی چی برای یک نوع داده؟ این حالت تمام کلیدهایی که توی [] هستن رو استخراج و مقدارشون رو از توی رشته پیدا میکنه. حالا باز چک میکنم ببینم کد بهتری میتونم بنویسم یا نه.


یعنی روی داده های زیر کار نمی کند :


$t = 'salam[id]s[title]oobiii[name]chetorii';
$s = 'salam1sooooobiiiALIchetorii';

abolfazl-z
شنبه 15 تیر 1392, 12:46 عصر
درضمن چرا هر یک کاراکتر فارسی در php دو کاراکتر به حساب می آید ؟

یعنی :


echo strlen('ل');

خروجی هست 2 !؟ :متفکر:

abolfazl-z
شنبه 15 تیر 1392, 13:31 عصر
خوب من تونستم برنامه اش رو بنویسم خیلی دشوار بود ولی تموم شد.اما خود برنامه نیست تابع مفیدی نوشتم که تمام کار برنامه رو این تابع انجام می دهد.
خوب فقط بهینه سازی و یک سری کار ها میمونه که اگر جناب آقای شهرکی شما لطف کنید انجام بدهید ممنون میشم.این تابع در بعضی مواقع نمیتونه کار کنه که اگر تونستیم(چون بعید بدانم) درست اش می کنیم.


<?php
//$s1 = 'salam[id]s[title]oobiii[name]chetorii'; [] = remove
$s1 = 'salamsoobiiichetorii';
$s2 = 'salam1sooooobiiiALIchetorii';
function get_def($s1,$s2)
{
$i=0;
$b=0;
$t=0;
$buffer = array();

while(true)
{
start:
if(substr($s1,$i,1)!==substr($s2,$b,1))
{
while(true)
{
$t++;
if(substr($s1,$i,1)==substr($s2,$b+$t,1))
{
$buffer[] = substr($s2,$i,$t);
$s2 = remove_str($s2,$i,$i+$t-1);
$i=0;$b=0;$t=0;
goto start;
}
else
if(strlen($s1)-1== $i+$t && count($buffer)==0)
{
if(strlen($s1) < strlen($s2))
{
$buffer[] = substr($s2,strlen($s1),strlen($s2)-strlen($s1));
return $buffer;
}
else
return 'false3';
}
elseif(strlen($s1)-1== $i+$t && count($buffer)>0)
{
if(strlen($s1) < strlen($s2))
{
$buffer[] = substr($s2,strlen($s1),strlen($s2)-strlen($s1));
return $buffer;
}
else
return $buffer;
}
};
}
if(strlen($s1)-1== $i && count($buffer)==0)
{
if(strlen($s1) < strlen($s2))
{
$buffer[] = substr($s2,strlen($s1),strlen($s2)-strlen($s1));
return $buffer;
}
else
return 'false1';
}
elseif(strlen($s1)-1== $i && count($buffer)>0)
{
if(strlen($s1) < strlen($s2))
{
$buffer[] = substr($s2,strlen($s1),strlen($s2)-strlen($s1));
return $buffer;
}
else
return $buffer;
}

$i++;
$b++;
}
}
function remove_str($string,$start,$end)
{
$s1 = substr($string,0,$start);
$s2 = substr($string,$end+1,strlen($string)-$end+1);
return $s1.$s2;
}

print_r(get_def($s1,$s2));

?>

خوب کار تابع get_def این هست که میاد هر چی که توی رشته دوم نسبت به اول کم داره را داخل آرایه قرار میدهد خوب حتما می گویید چه ربطی دارد خوب فقط ما باید
ها را حذف کنیم و رشته رو به تابع بدهیم.

کار تابع remove_str این هست که میاد اول رشته مورد نظر رو میگیره سپس با مقدار دهی به پارامتر اول و دوم میاد رشته رو حذف میکنه و بر میگردونه(پارامتر اول رشته مورد نظر ، پارامتر دوم محل شروع رشته برای حذف, پارامتر سوم محل انتهای رشته برای حذف)

MMSHFE
یک شنبه 16 تیر 1392, 14:23 عصر
$t = 'salam[id]s[title]oobiii[name]chetorii';
$s = 'salam1sooooobiiiALIchetorii';
function GetKeys($template, $string) {
$found = array();
$keys = array();
if(preg_match_all('#\[(.*?)\]#', $template, $keys)) {
$strParts = array();
$start = 0;
$keys = $keys[1];
foreach($keys as $key) {
$template = str_replace('[' . $key . ']', '[]', $template);
}
$strParts = explode('[]', $template);
$count = count($strParts);
for($i = 1; $i < $count; $i++) {
$start = strpos($string, $strParts[$i - 1], $start) + strlen($strParts[$i - 1]);
$end = strpos($string, $strParts[$i], $start) - $start;
$found[$keys[$i - 1]] = substr($string, $start, $end);
}
}
return $found;
}
print_r(GetKeys($t, $s));

اینو تست کنید. درست کار میکنه.
اما درمورد حروف فارسی، چون یونیکد هستن، هر کارکتر 2 بایت فضا اشغال میکنه و بخاطر همین دوبرابر میشماره. برای حروف فارسی باید از توابع MultiByte که با _mb شروع میشن استفاده کنید (mb_strlen و mb_substr و...).