الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

لماذا التعابير القياسية(regex) المعقدة (قليلاً) تcrashعمل للجافا

بدأه اسد الاسود في 19 أبريل 2009 · 14 رد · 1,641 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه ،،

لدي مشكلة منذ ان بدأت في تعلم الجافا وانا ارى اشياء غير معقولة :-) مثلا لماذا عند عمل تعبير قياسي معقد قليلا يعمل لاحظ يعمل وعند ازدياد حجم المحتوى الذي يبحث داخله لو زيادة بسيطة يقوم بعمل كراش

لماذا لا يتم تنضيف المموري من التعبير القياسي فانا لا احتاج الا الى الرفرنس وبعض الاحيان اجد اني لا اضع اي رفرنس ولكن الREGEX المحترم يقوم بتحطيم وتمزيق الجافا !!

حقيقة انا استعملت عدة لغات لم ارى لغة بهذا الغباء مع التعابير القياسية

ما يهمني اني وجدت حل لهذه المعضلة وهي وجود باكج يقوم بعمل نفس عمل التعابير القايسية اختلاف انه لا يجهد الميموري ولا يعمل StackOverflowError

هذا عنوان الباكج http://jregex.sourceforge.net/download.html

للمعلومية ايضا هناك باكج jregex وهي يقال انها قوية واسرع من util.regex

تعديل: تم أضافة باكج JREGEX بدلا من باكج javaregex لقوة الباكج لرؤية مثال على JREGEX انتقل للمشاركة 10 من هنا

تم تعديل هذه المشاركة بواسطة اسد الاسود في 20 أبريل 2009 في 11:58

#2

جرب الكود التالي وانظر الى المخرجات

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class badRegex
{  
 public static void main(String[] args) {
  String long_string = "";
  for(int i = 0; i < 15; ++i)
   long_string += "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n";
   System.out.println(long_string);

  if (Pattern.matches("\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)", long_string))
   System.out.println("foo");
  else
   System.out.println("bar");
 }
}

الان قم بتنفيذ الكود التالي:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class badRegex
{  
 public static void main(String[] args) {
  String long_string = "";
  for(int i = 0; i < 12; ++i)
   long_string += "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n";
   System.out.println(long_string);

  if (Pattern.matches("\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)", long_string))
   System.out.println("foo");
  else
   System.out.println("bar");
 }
}

هل عرفت الفرق بين الاثنين فقط ان الاول string اكبر ب3 اسطر هذا يعني ان التعبير اذا زاد حجم المعطيات ولو تلاحظ انها قليلة جدا يقوم بعمل كراش

لان فـ الجافا لا يتم عمل التعابير مثل اللغات الثانية صراحة بعد اكتشافي لهذا الامر خاب املي كثيرا في الجافا مع انها لغة قويةالا انها تتدمر بسبب زيادة 3 اسطر !!!!

ماعلينا ;-(

الرجاء المشاركة او على الاقل رفع الملف :-)

#3

هل تريد رأيي؟

المشكلة فيك وليس في الجافا

هل هناك من يقوم بعملية concatenation لجملة String كل هذا القدر من المرات

ثم تستغرب أنك تحصل على Crash

هل تعرف مقدار الذاكرة التي أهدرتها؟

تعلم جافا جيداً ثم تكلم عن كون الجافا لغة سيئة جداً

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#4

انا مع اخي علاء في رأيه ..

استخدم في عملية الدمج StringBuilder بدلا من String

#5

السلام عليكــم ورحمـة الله وبركاتــه ،،

اقتباس
حقيقة انا استعملت عدة لغات لم ارى لغة بهذا الغباء مع التعابير القياسية

لو تتفضل وتقوم بتصميم لغة برمجة أكثر ذكاء في التعامل مع Regex

أما الإكتفاء بالنقد غير البناء واتهام الناس الذين يقومون يعمل جبار ليقدموا لنا لغة برمجة متكاملة بالغباء، فهذا هو ****** بعينه

ثم ماذا تعتي بهذا التعبير

\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)

كان يمكن اختصاره في

"(?:\\w+\\n)+"

تم تعديل هذه المشاركة بواسطة herch في 19 أبريل 2009 في 21:05

#6

لاحظ الفرق بين استخدام كل من StringBuilder - StringBuffer - String

public class Comparing {

	public Comparing(){
		StringBufferThread t1 = new StringBufferThread();
		StringThread t2 = new StringThread();
		StringBuilderThread t3 = new StringBuilderThread();

		t1.start();
		t2.start();
		t3.start();
	}

	public static void main(String[]args){
		new Comparing();
	}
	public class StringBuilderThread extends Thread
	{
		public void run(){
			StringBuilder str = new StringBuilder();
			for(int i = 0; i < 1111111; i ++){
				str.append("Mohamed\n");
			}

			System.out.println("StringBuilder finish");
		}
	}
	public class StringBufferThread extends Thread
	{
		public void run(){
			StringBuffer str = new StringBuffer();
			for(int i = 0; i < 1000000; i ++){
				str.append("Mohamed\n");
			}
			System.out.println("StringBuffer finish");
		}
	}
	public class StringThread extends Thread
	{
		public void run(){
			String str = "";
			for(int i = 0; i < 10000; i ++){
				str += "Mohamed\n";
			}
			System.out.println("String finish");
		}
	}
}

النتيجة

StringBuilder finish
StringBuffer finish
String finish

#7

ماشاء الله هجوم موحد طيب انا سويت الكود السابق للاختصار جرب التالي وعلمني ياعلاء

  
String long_string = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
  if (Pattern.matches("\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)", long_string))
   System.out.println("foo");
  else
   System.out.println("bar");

بدون لووب لكي اثبت لك ان كلامي صحيح واذا ما اقتنعت ممكن اجيبلك مراجع

#8

أنت هنا تستخدم + وفي كل مرة تستخدمها سيتم بناء String جديدة

لهذا أخبرتك أن خبرتك في جافا ضعيفة

وليس من حقك أن تحكم عليها

بالنسبة لموضوع regex نفسه أعرف أن هناك مشكلة

لكن لا تستطيع الحكم على لغة برمجة كجافا لمجرد أن حزمة فيها لا تعمل بشكل جيد

نقطة على الهامش:

بالله عليك هل تظنني لا أفهم تكرار for لكي تكتب لي المشاركة السابقة؟

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#9

ياعزيزي , هذا مجرد مثال ماذا لو اخبرتك اني استعمل

StringBuffer في مشروعي ولكن وضعت لكم مثال على String لكي تصل الفكرة الى اكبر عدد

انظر للكود التالي واخبرني بالنتيجة

	  StringBuffer pageBuffer = new StringBuffer();

	  for(int l=0;l<=15;++l)
		pageBuffer.append("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");

	if (Pattern.matches("\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)",pageBuffer.toString()))
	 System.out.println("foo");
	  else
	 System.out.println("bar");

ملاحظة على الهامش: من تواضع لله رفعه

#10

هههههههههههههههههههههههههههههههه جربت JREGEX الي تكلمت عنها في نهاية الموضوع صارت افضل من الحل الي وضعته

تخيل الفرق الكبير يعمل بحث على 150 سطر ويستبدلها + يقوم بالتأكد من التعبير هل هو مطابق على النص ام لا

-لاحظ يستبدلها وليس مجرد يشيك عليها بسرعة هائلة وليس 15 سطر ويــهنق :-)

لتحميل JREGEX

حمل الملف من المرفقات وفك الضغط عنه ستجد مجلد موجود به الباكج وملف جافا مثال على طريقة استخدام البكج

نفس الملف كتبته هنا

import jregex.*;// استدعاء لبكج ج ريجيكس
public class GoodRegex
{  
 public static void main(String[] args) {

	  StringBuffer pageBuffer = new StringBuffer();
	  for(int l=0;l<=150;++l)
	  pageBuffer.append("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");

	  String contents=pageBuffer.toString();	
	  Pattern p=new Pattern("\\A((?:.|\\n)*?)?([\r\n]{1,2}|--)");// ضع التعبير القياسي هنا
	  Replacer r=p.replacer(" <- $1 -> \n");// اذا اردت الاستبدال تضع ما تريد الاستبدال به ملاحظة علامة الدولار تعني الريفرنس اي ريفرنس 1
	   contents=r.replace(contents);// للاستبدال

	  Matcher m=p.matcher(pageBuffer.toString());//للمطابقة
		 if(m.matches())// للتأكد إذا كان متطابق
			System.out.println("التعبير المستعمل موجود");
		  else
			System.out.println("التعبير القياسي لاينطبق على النص");
	  System.out.println(contents);
 }
}

البكج له مميزات لن تجدها اصلا في المكتبة الاساسية لـregex في جافا

هذا الDocumentation

http://jregex.sourceforge.net/doc-index.html

jregex.rar

#11

اخي اسد انت تنظر للموضوع من جانب واحد

لغات البرمجة التي تتكلم عنها ..ليست افضل حال في هذا الموضوع من الجافا

بالسي شارب نفس الموضوع ونفس المعاناة

وقد نحاج بالسي بلس بلس لعملية تحميل زائد لـمعامل (+) ..اذا اردت ان تستخدم هذه الخطوة

كما قال لك علاء

اقتباس
أنت هنا تستخدم + وفي كل مرة تستخدمها سيتم بناء String جديدة

وهذا منطقيا بعيد عن اصول البرمجة

قدمو لك الاخوة حلول لتفادي هذه الثغرة ..فلما تصر عليها ..

لا يوجد لغة برمجة مكتملة ..

انت محق في نظريتك التي قد اقنعك بها احد ما

لكن اذا اردنا ان نحكم على لغة من وراء عيب واحد ..فالصراحة لن تبقى الا الجافا في الاجواء -_-

بالتوفيق

الله معك .

#12

اخي العزيز انا لا اتكلم عن مشكلة String ((((انا فقط وضحت المشكلة بها لكي تصل الى اكبر عدد ممكن)))) ,

لا اعلم لماذا اللف والدوران حول String انا وضعت مثال بأستخدام StringBuffer لماذا لم يعلق عليه احد ؟؟!!

اولا : -- المشكلة اذا كبر المحتوى المبحوث من قبل REGEX مثلا 15 سطرا -- فهو يعمل كراش(ملاحظة -لم اقوم بعمل اي استبدال - فقط تأكدت ان النص ينطبق عليه التعبير القياسي)

ستجد ان الجافا على طول يعملك Crash مع الملاحظة اني قمت بتغيير الباكج تبع الجافا وقمت بأستعمال JREGEX اذهب لهذه المشاركة هنا ستجد اني اضفت 150 سطرا تخيل !! ولم يحدث كراش بل انه سرعته فائقة واسرع من الباكج الاصلي حتى اني قمت بالاستبدال (و) عمل تأكد من مطابقة النص للتعبير القياسي

ثانيا : -- في الصفحة الاولى ستجدني استخدمت StringBufferهنا رد على الاشخاص الذين قالوا ان المشكلة من String وانك انسان ما تفهم ولاتعي شئ في البرمجة

انا هدفي في الموضوع ان ابين للاشخاص المبتدئين في الجافا ويتعاملون مع ان المشكلة ليست منهم انما المشكلة من REGEX تبع الجافا (انهم لا يتبعون الطريقة الاصلية للREGEX بل يتبعون طريقة الشجرة بأمكانك البحث عن هذه المشكلة )

ثالثا:-- انا لم احكم على جافا بانها لغه ليس لها اهمية لمجرد باكج واحد وتجدني وضعت حل -وهو استبداله ببكج JREGEX- بل قلت انها لغه قوية لكن خاب املي عندما رايت REGEX ليس لها أهمية في الجافا المشكلة ان الاشخاص هنا لا يدققون في الكلمات وعلى ماذا ترجع فقط يقوم بالهجوم عندما تقوم بنقد لغة او اي شئ كان _ياترا لماذا عضويتي منذ 2003 ولم اكتب الا 30 مشاركة_

تم تعديل هذه المشاركة بواسطة اسد الاسود في 20 أبريل 2009 في 11:46

#13

السلام عليكم

ما معنى هذا التعبير ...

"\\A((?:.|\\n)*?)?([\r\n]{1,10}|--)"

اعتقد ان المشكله في هذا التعبير ...

عندي صنف استخدمه لتحقق من المدخلات باستخدام التعابير

ولم اجد فيه مشكله ... حتى بعد اضافة 1150 سطر ...

تم تعديل هذه المشاركة بواسطة العيافـي في 20 أبريل 2009 في 15:50

#14

ياعزيزي المشكلة من جافا نفسها انا في مشروعي اقوم بإدخال ملفات XML واقوم بعمل عمليات بالتعابيير , لاتقولي استخدم XML Parser

لان اولا Parser لا يعرف يتعامل مع الفراغات لازم يكون<course>J2me</course> لكن ماذا لو اخطأ المدخل ووضع

< course >

J2me

< / course > ادخاله صحيح فهل تجعل مسافات تفسد عملك

انا في هذه الحالة مضطر اني اضع تعبير كهذا

(<\s*(\w*)[^>]*?>((?:.*?\s*?)+)<\s*?/\s*?(\w*)\s*?>)

لاحظ انه ملف XML ملئ ربما يصل على الاقل الى عشرين سطر مثل هذا

تخيل تقوم بعمل البرنامج لشركة ويقوم بعمل كراش ماذا ستفعل ف هذه الحالة - ستكون لاتفقه في البرمجة شئ - حكمة من احد الحكماء

اتمنى تضع الفئة الي تتكلم عنها وانها تقبل اكثر من 2000 سطر بأستعمال الutil.regex (لا اكذبك لكن لكي يطمئن قلبي )

#15

يا اخي الكريم

ارغب في معرفه الهدف من هذا التعبير .... هل تقصد بان كل هذا التعبير لحل مشكله الفراغات ...

ثانيا عندما يكون هناك وسم بهذا الشكل < tag > يعتبر الخطأ في ملف XML .

هذا مثالين لتحقق

1- من ان القيمه المدخله تبدأ بنص معين ..

2- من ان القيمه المدخل ارقام

public static boolean isBegin(String text, String c){
		return text.matches("^["+c+"](.*)");
	}
	public static boolean isNumeric(String text){
		return text.matches("\\d{1,}");
	}

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…