ضروری: مشکل با regular expression ها

golden

Member
من این مشکل را توی یه انجمن انگلیسی هم گفتم ولی مثل اینکه همه از regular expression ها میترسند. اکثرا به من پیشنهاد کرده اند که کار با regex ها را بیخیال شم. اما کار من گره خورده به استفاده از regexها.
گفتم بیام اینجا بگم شاید هموطنام یه کمکی به من بکنند.
مشکل اینجاست: من میخواهم یه فایل html را لود کنم و بعد توی textbox ها و textarea های موجود توی اون یه سری از مقادیر که از دیتابیس خونده میشه را بریزم و بعد اون را به کاربر نمایش بدم.
این کد html مورد نطر منه:
کد:
<textarea name="textarea"></textarea>
<textarea name="textarea2"></textarea>
<textarea name="textarea3"></textarea>

اینم regexهای منه که با استفاده از eregi_replace اونا را اجرا میکنم:
کد:
$regex = '<(textarea)(.*)(name=)("|\')(textarea)("|\')(.*)</textarea>';
$repregex = '<\1\2\3\4textarea\4\7one</\1>';
$file = eregi_replace($regex,$repregex,$file);
$regex ='<(textarea)(.*)(name=)("|\')(textarea1)("|\')(.*)</textarea>';
$repregex = '<\1\2\3\4textarea1\4\7tow</\1>';
$file = eregi_replace($regex,$repregex,$file);
$regex ='<(textarea)(.*)(name=)("|\')(textarea3)("|\')(.*)</textarea>';
$repregex = '<\1\2\3\4textarea\4\7three</\1>';
$file = eregi_replace($regex,$repregex,$file);

اما متاسفانه جوابی که php به من برمیگردونه اونی نیست که من میخواهم. نتیجه کارهای php اینه:
کد:
<textarea name="textarea"></textarea>
<textarea name="textarea2"></textarea>
<textarea name="textarea3">onetwothree</textarea>

اما من انتظار داشتم که اینو به من برگردونه:
کد:
<textarea name="textarea">one</textarea>
<textarea name="textarea2">two</textarea>
<textarea name="textarea3">three</textarea>

من از این در شگفتم که وقتی از موتورهای دیگه regex مثل editpadpro استفاده میکنم جواب درست به من برمیگردونند ولی php نه 8O :!: (البته بگم که من این کار را هم با php5 و هم با php4 انجام دادم ولی نتیجه هر دو یکی شد.)
 

mazoolagh

Active Member
ظاهرا از آخر به اول پردازش ميكنه براي همين يك مقدار منحصر بفرد براي هر textarea بگذار درست ميشه! ولي سوال برانگيزه - اگر كسي منطق دقيق كارشو ميدونه بگه ...

کد:
<%
$file1 = '<textarea name="textarea1">1</textarea>' ;
$file2 = '<textarea name="textarea2">2</textarea>' ;
$file3 = '<textarea name="textarea3">3</textarea>' ;
$file4 = '<textarea name="textarea4">4</textarea>' ;
$file = $file1.$file2.$file3.$file4 ;
print $file."<br>" ;

$regex = '<(textarea)(.*)(name=)(\"|\')(textarea1)(\"|\')(.*)>1</(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>one</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

$regex = '<(textarea)(.*)(name=)(\"|\')(textarea2)(\"|\')(.*)>2</(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>two</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

$regex = '<(textarea)(.*)(name=)(\"|\')(textarea3)(\"|\')(.*)>3</(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>three</\8>' ; 
$file = eregi_replace($regex,$repregex,$file);

$regex = '<(textarea)(.*)(name=)(\"|\')(textarea4)(\"|\')(.*)>4</(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>four</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

print $file."<br>" ;
%>
 

golden

Member
نتيج كد شما اين شد:
کد:
<textarea name="textarea1">1</textarea><textarea name="textarea2">2</textarea><textarea name="textarea3">3</textarea><textarea name="textarea4">4</textarea><br><textarea name="textarea1">one</textarea><textarea name="textarea2">two</textarea><textarea name="textarea3">three</textarea><textarea name="textarea4">four</textarea><br>

البته من نمي تونم فايلم را چند تيكه كنم بعد به هم جوش بدم.
 

golden

Member
مشكل اينجاست كه اون كدهاي html را من نمي سازم بلكه كاربر بايد اونا را بسازه پس من هيچ اختياري ندارم........
 

mazoolagh

Active Member
1- اون پرينت اول رو بخاطر تست گذاشتم شما اون رو حذف كن! تا خروجي درست بشه!

2- چيزي كه عجيبه اينه كه شما نه در پترن و نه در خود عبارت كارآكتر < بستن تگ textarea رو نگذاشتي ولي كار ميكنه!

3- من يك تست با regexpهاي asp ميكنم ببينم اونجا هم همينطوري هست يا نه؟

4- فكر ميكنم يك نكته اي در نحوه پردازش هست كه بايد در نظر گرفته بشه تا پترن رو درست تعريف كرد (هر چند كه ظاهرش درست هست!)
 

mazoolagh

Active Member
گلدن جان عجب اشتباه ظريفي كردي! تازه الان كه بيشتر دقت كردم فهميدم. اين (.*) كه گذاشتي به اين عنوان كه حداقل يك فاصله رو پيدا كنه اشتباه هست بايد تبديلش كني به ( ?) تا درست بشه. ديگه لازم نيست مقدار اوليه بدي!

کد:
<%

$file1 = '<textarea name="textarea1"></textarea>' ;
$file2 = '<textarea name="textarea2"></textarea>' ;
$file3 = '<textarea name="textarea3"></textarea>' ;
$file4 = '<textarea name="textarea4"></textarea>' ;
$file = $file1.$file2.$file3.$file4 ;
print $file."<br>" ;

$regex = '<(textarea)( ?)(name=)(\"|\')(textarea1)(\"|\')( ?)></(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>one</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

$regex = '<(textarea)( ?)(name=)(\"|\')(textarea2)(\"|\')( ?)></(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>two</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

$regex = '<(textarea)( ?)(name=)(\"|\')(textarea3)(\"|\')( ?)></(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>three</\8>' ; 
$file = eregi_replace($regex,$repregex,$file);

$regex = '<(textarea)( ?)(name=)(\"|\')(textarea4)(\"|\')( ?)></(textarea)>' ; 
$repregex = '<\1\2\3\4\5\6\7>four</\8>' ; 
$file = eregi_replace($regex,$repregex,$file); 

print $file."<br>" ;

%>

ضمنا منظورتو از چند تكه كردن و بعد وصل كردن بهم درست نفهميدم. من توي مثال اينطوري نوشتم كه راحتتر باشه. مسلما شما ميتوني مستقيما $file رو استفاده كني!
 

golden

Member
mazoolagh عزیز ممنون از کمکت. اما من اون (*.) را برای این گذاشتم که شامل همه کاراکترها بشه و به هر چند تا. مثلا اگه ما کد زیر را داشتیم. این regex اون را هم به شمار بیاره و با مقدار دیگری جایگزینش کنه:
کد:
<textarea rows="2" name="textarea1" cols="20" tabindex="1">

با کدی که شما دادی فقط یه فاصله بین name و textarea> قرار دادی. اما ممکنه کاربر چیزایی مثل تعداد خطوط را قبل از name بیاره و اون وقته که regex ما کار نمیکنه.
 

sarallah

Member
mazoolagh جان معذرت که دخالت میکنم ...
golden جان شما از کد زیر استفاده کن ببین مشکلت حل میشه ....


کد:
<?PHP
$file1 = '<textarea rows="5" name="textarea1" cols="20"></textarea>' ;
$file2 = '<textarea rows="5" name="textarea2" cols="20"></textarea>' ;
$file3 = '<textarea rows="5" name="textarea3" cols="20"></textarea>' ;
$file4 = '<textarea rows="5" name="textarea4" cols="20"></textarea>' ;
$file = $file1.$file2.$file3.$file4 ;
print $file."<br><br>" ;

$regex = '<(textarea)([[:alnum:]= \"]*)(name=)(\"|\')(textarea1)(\"|\')([[:alnum:]= \"]*)></(textarea)>' ;
$repregex = '<\1\2\3\4\5\6\7>one</\8>' ;
$file = eregi_replace($regex,$repregex,$file);

$regex = '<(textarea)([[:alnum:]= \"]*)(name=)(\"|\')(textarea2)(\"|\')([[:alnum:]= \"]*)></(textarea)>' ;
$repregex = '<\1\2\3\4\5\6\7>two</\8>' ;
$file = eregi_replace($regex,$repregex,$file);

$regex = '<(textarea)([[:alnum:]= \"]*)(name=)(\"|\')(textarea3)(\"|\')([[:alnum:]= \"]*)></(textarea)>' ;
$repregex = '<\1\2\3\4\5\6\7>three</\8>' ;
$file = eregi_replace($regex,$repregex,$file);

$regex = '<(textarea)([[:alnum:]= \"]*)(name=)(\"|\')(textarea4)(\"|\')([[:alnum:]= \"]*)></(textarea)>' ;
$repregex = '<\1\2\3\4\5\6\7>four</\8>' ;
$file = eregi_replace($regex,$repregex,$file);

print $file."<br>" ;

?>
 

golden

Member
ممنون از لطف شما سارالله جان. من یه regex با pregها نوشتم درست تد.اما دست شما هم درد نکنه.....

فکر کنم تنها نکته کار این بود که من نباید از .(dot) استفاده میکردم.

از شما هم ممنون mazoolagh
 

mazoolagh

Active Member
ثارالله جان! من تو همين مونده بودم كه چي بايد بجاي نقطه ستاره بذاريم كه درست بشه!!! فقط يك نكته داره و اون هم اينكه اگر توي property هاي tag فرضا : داشته باشيم مثل style ديگه عمل نميكنه. يعني هنوز بايد اصلاح بشه.

كد پايين رو از vbscript هاي خودم تبديل كردم به php :
کد:
<%

$file1 = '<textarea rows="2" cols="20" name="textarea1" style="background-color:wheat" dir="rtl"></textarea>' ;
$file2 = '<textarea rows="3" cols="22" name="textarea2" style="background-color:khaki" dir="rtl"></textarea>' ;
$file3 = '<textarea rows="4" cols="18" name="textarea3" style="background-color:tan" dir="rtl"></textarea>' ;
$file4 = '<textarea rows="3" cols="26" name="textarea4" style="background-color:steelblue" dir="rtl"></textarea>' ;
$file5 = '<textarea rows="2" cols="16" name="textarea5" style="background-color:bisque" dir="rtl"></textarea>' ;
$file = $file1.$file2.$file3.$file4.$file5 ;

$tag_names = array("textarea1", "textarea2", "textarea3", "textarea4", "textarea5") ;
$tag_texts = array("one", "two", "three", "four", "five") ;

for ($i=0;  $i<count($tag_names); $i++) {
	$ptrn = '(name=)(\"|\')('.$tag_names[$i].')(\"|\')' ; 
	$file = myreplace($ptrn , $file , $tag_texts[$i]) ;
}

print $file."<br>" ;

//=========================================================================
function myreplace($ptrn , $strng , $rep) {
	eregi($ptrn , $strng , $y) ;
	$n = stripos($strng , $y[0]) ;
	$n1 = strpos($strng , ">" , $n++) ;
	$n2 = strpos($strng , "<" , $n1++) ;
	return substr($strng , 0 , $n1).$rep.substr($strng , $n2) ;
}
%>

ضمنا گلدن جان اگه لطف كني كد اصلاح شده ات رو بگذاري خوبه
 

golden

Member
البته استایل به خودی خود مشکلی نداره اما اگه ما برای بیان رنگ در استایل از علامت # استفاده کنیم. دیگه regex ما کار نمیکنه.
منم برای اینکه این مشکلات پیش نیاد از دات استفاده کردم تا همه کاراکترها را بپوشونه. اما بدبختانه......

حالا برای رفع این مشکل کافیه به جای
کد:
([[:alnum:]= \"]*)
از
کد:
([[:alnum:]= #\"]*)
استفده کنیم.
 

جدیدترین ارسال ها

بالا