RegEx ریگولر ایکسپریشن کیا ہے؟
درحقیقت، ریگولر ایکسپریشن (جاوا میں RegEx) متن میں سٹرنگ تلاش کرنے کا ایک نمونہ ہے۔ جاوا میں، اس پیٹرن کی ابتدائی نمائندگی ہمیشہ ایک سٹرنگ ہوتی ہے، یعنی اسٹرنگ کلاس کا ایک آبجیکٹ۔ تاہم، کسی بھی سٹرنگ کو ریگولر ایکسپریشن میں مرتب نہیں کیا جا سکتا، صرف وہی جو ریگولر ایکسپریشن لکھنے کے اصولوں کی تعمیل کرتے ہیں - زبان کی تصریح میں بیان کردہ نحو۔ ریگولر ایکسپریشن لکھنے کے لیے، حروف تہجی اور عددی حروف کے ساتھ ساتھ میٹا کریکٹرز کا استعمال کیا جاتا ہے - وہ حروف جو ریگولر ایکسپریشن کے نحو میں ایک خاص معنی رکھتے ہیں۔ مثال کے طور پر:String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;
جاوا میں باقاعدہ تاثرات بنانا
جاوا میں RegEx بنانے کے لیے، آپ کو دو آسان مراحل پر عمل کرنے کی ضرورت ہے:- ریگولر ایکسپریشن نحو کا استعمال کرتے ہوئے اسے سٹرنگ کے طور پر لکھیں؛
- اس تار کو باقاعدہ اظہار میں مرتب کریں؛
Pattern
۔ ایسا کرنے کے لیے، آپ کو کلاس میں دستیاب دو جامد طریقوں میں سے ایک کو کال کرنا ہوگا compile
۔ پہلا طریقہ ایک دلیل لیتا ہے - ایک ریگولر ایکسپریشن کا سٹرنگ لٹریل، اور دوسرا - نیز ایک اور پیرامیٹر جو متن کے ساتھ ٹیمپلیٹ کا موازنہ کرنے کے موڈ کو آن کرتا ہے:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
ممکنہ پیرامیٹر کی قدروں کی فہرستflags
کلاس میں بیان کی گئی ہے Pattern
اور ہمارے لیے جامد کلاس متغیرات کے طور پر دستیاب ہے۔ مثال کے طور پر:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
بنیادی طور پر، کلاس Pattern
ایک باقاعدہ اظہار کنسٹرکٹر ہے. ہڈ کے نیچے، طریقہ compile
کلاس کے نجی کنسٹرکٹر کو Pattern
ایک مرتب شدہ منظر بنانے کے لیے کال کرتا ہے۔ ٹیمپلیٹ مثال بنانے کا یہ طریقہ اسے ایک ناقابل تغیر آبجیکٹ کے طور پر تخلیق کرنے کے مقصد کے ساتھ لاگو کیا جاتا ہے۔ تخلیق کرتے وقت، ریگولر ایکسپریشن کی نحوی جانچ پڑتال کی جاتی ہے۔ اگر لائن میں غلطیاں ہیں تو، ایک استثناء پیدا ہوتا ہے PatternSyntaxException
۔
باقاعدہ اظہار نحو
باقاعدہ اظہار نحو علامتوں کے استعمال پر مبنی ہے<([{\^-=$!|]})?*+.>
، جسے حروف تہجی کے ساتھ ملایا جا سکتا ہے۔ ان کے کردار پر منحصر ہے، وہ کئی گروہوں میں تقسیم کیا جا سکتا ہے:
میٹا کریکٹر | مقصد |
---|---|
^ | لائن کا آغاز |
$ | لائن کے اختتام |
\b | لفظ کی حد |
\B | لفظ کی حد نہیں |
\A | ان پٹ کا آغاز |
\G | پچھلے میچ کا اختتام |
\Z | ان پٹ کا اختتام |
\z | ان پٹ کا اختتام |
میٹا کریکٹر | مقصد |
---|---|
\d | ڈیجیٹل علامت |
\D | غیر عددی کردار |
\s | خلائی کردار |
\S | غیر وائٹ اسپیس کردار |
\w | حروف عددی کردار یا انڈر سکور |
\W | حروف تہجی، عددی، یا انڈر سکور کے علاوہ کوئی بھی کردار |
. | کوئی بھی کردار |
میٹا کریکٹر | مقصد |
---|---|
\t | ٹیب کردار |
\n | نئی لائن کردار |
\r | گاڑی کی واپسی کا کردار |
\f | نئے صفحہ پر جائیں |
\u0085 | اگلی لائن کا کردار |
\u 2028 | لائن الگ کرنے والا کردار |
\u 2029 | پیراگراف الگ کرنے والی علامت |
میٹا کریکٹر | مقصد |
---|---|
[a B C] | مندرجہ بالا میں سے کوئی بھی (a، b، یا c) |
[^abc] | درج فہرست کے علاوہ کوئی بھی نہیں (a, b, c نہیں) |
[a-zA-Z] | رینج ضم کرنا (لاطینی حروف a سے z تک غیر حساس ہیں) |
[اشتہار[ایم پی]] | حروف کا مجموعہ (a سے d اور m سے p) |
[az&&[def]] | علامتوں کا تقطیع (علامتیں d,e,f) |
[az&&[^bc]] | گھٹانے والے حروف (حروف a، dz) |
میٹا کریکٹر | مقصد |
---|---|
? | ایک یا لاپتہ |
* | صفر یا اس سے زیادہ بار |
+ | ایک یا زیادہ بار |
{n} | n اوقات |
{n،} | n بار یا اس سے زیادہ |
{n,m} | n بار سے کم اور m بار سے زیادہ نہیں۔ |
لالچی کوانٹیفائر موڈ
کوانٹیفائرز کی ایک خاص خصوصیت انہیں مختلف طریقوں میں استعمال کرنے کی صلاحیت ہے: لالچی، انتہائی لالچی اور سست۔ اضافی لالچی موڈ کو+
کوانٹیفائر کے بعد "" کی علامت اور سست موڈ کو " ?
" شامل کرکے آن کیا جاتا ہے ۔ مثال کے طور پر:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
اس ٹیمپلیٹ کو بطور مثال استعمال کرتے ہوئے، آئیے یہ سمجھنے کی کوشش کرتے ہیں کہ کوانٹیفائر مختلف طریقوں میں کیسے کام کرتے ہیں۔ پہلے سے طے شدہ طور پر، کوانٹیفائر لالچی موڈ میں کام کرتا ہے۔ اس کا مطلب ہے کہ یہ سٹرنگ میں سب سے طویل ممکنہ میچ کی تلاش میں ہے۔ اس کوڈ کو چلانے کے نتیجے میں:
public static void main(String[] args) {
String text = "Egor Alla Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
ہمیں مندرجہ ذیل آؤٹ پٹ ملے گا: Alla Alexa دیے گئے پیٹرن " " کے لیے سرچ الگورتھم А.+а
درج ذیل ترتیب میں انجام دیا جاتا ہے۔
-
دیے گئے پیٹرن میں، پہلا حرف روسی حرف کا کریکٹر ہے
А
۔Matcher
صفر کی پوزیشن سے شروع ہونے والے متن کے ہر حرف سے اس سے میل کھاتا ہے۔ ہمارے متن میں صفر کی پوزیشن پر ایک علامت ہےЕ
، لہذاMatcher
یہ متن کے حروف کو ترتیب وار اس وقت تک گزرتا ہے جب تک کہ یہ پیٹرن سے مماثل نہ ہو۔ ہماری مثال میں، یہ پوزیشن نمبر 5 پر علامت ہے۔ -
پیٹرن کے پہلے کریکٹر کے ساتھ میچ ملنے کے بعد،
Matcher
یہ پیٹرن کے دوسرے کریکٹر کے ساتھ میچ کو چیک کرتا ہے۔ ہمارے معاملے میں، یہ علامت ہے ".
"، جو کسی بھی کردار کے لیے کھڑا ہے۔چھٹی پوزیشن میں حروف کی علامت ہے
л
۔ یقینا، یہ "کسی بھی کردار" کے پیٹرن سے میل کھاتا ہے۔ -
Matcher
پیٹرن سے اگلے کردار کو چیک کرنے کے لیے آگے بڑھتا ہے۔ ہماری ٹیمپلیٹ میں، یہ ".+
" کوانٹیفائر کا استعمال کرتے ہوئے بیان کیا گیا ہے۔ چونکہ پیٹرن میں "کسی بھی کردار" کی تکرار کی تعداد ایک یا زیادہ بار ہے، اس لیےMatcher
یہ سٹرنگ سے اگلا کریکٹر لیتا ہے اور پیٹرن کی تعمیل کے لیے اسے چیک کرتا ہے، جب تک کہ "کسی بھی کردار" کی شرط پوری ہو جائے، ہماری مثال میں - لائن کے آخر تک (مقام نمبر 7 سے - متن کے نمبر 18)۔درحقیقت،
Matcher
یہ پوری لائن کو آخر تک اپنی گرفت میں لے لیتا ہے - یہیں سے اس کا "لالچ" ظاہر ہوتا ہے۔ -
Matcher
متن کے آخر تک پہنچنے اور پیٹرن کے “” حصے کی جانچ مکمل کرنے کے بعدА.+
، میچر باقی پیٹرن - حرف حرف کی جانچ کرنا شروع کر دیتا ہےа
۔ چونکہ آگے کی سمت میں متن ختم ہو گیا ہے، چیک الٹ سمت میں ہوتا ہے، آخری حرف سے شروع ہوتا ہے: -
Matcher
پیٹرن " " میں تکرار کی تعداد کو "یاد رکھتا ہے.+
" جس پر یہ متن کے آخر تک پہنچا ہے، لہذا یہ تکرار کی تعداد کو ایک سے کم کرتا ہے اور متن کے پیٹرن کو چیک کرتا ہے جب تک کہ کوئی مماثلت نہ مل جائے۔
الٹرا لالچی کوانٹیفائر موڈ
انتہائی لالچی موڈ میں، میچر لالچی موڈ میکانزم کی طرح کام کرتا ہے۔ فرق یہ ہے کہ جب آپ لکیر کے آخر تک متن کو پکڑتے ہیں تو پیچھے کی طرف کوئی تلاش نہیں ہوتی ہے۔ یعنی سپر لالچی موڈ میں پہلے تین مراحل لالچی موڈ کی طرح ہوں گے۔ پوری سٹرنگ کیپچر کرنے کے بعد، میچر باقی پیٹرن کو جوڑتا ہے اور اس کا موازنہ کی گئی سٹرنگ سے کرتا ہے۔ ہماری مثال میں، پیٹرن "А.++а
" کے ساتھ مرکزی طریقہ کو انجام دیتے وقت، کوئی مماثلت نہیں ملے گی۔
سست کوانٹیفائر موڈ
-
اس موڈ میں، ابتدائی مرحلے پر، جیسے لالچی موڈ میں، پیٹرن کے پہلے کردار کے ساتھ ایک میچ تلاش کیا جاتا ہے:
-
اگلا، یہ پیٹرن میں اگلے کردار کے ساتھ ایک میچ تلاش کرتا ہے - کوئی بھی کردار:
-
لالچی موڈ کے برعکس، سست موڈ متن میں مختصر ترین مماثلت تلاش کرتا ہے، اس لیے پیٹرن کے دوسرے کریکٹر کے ساتھ مماثلت تلاش کرنے کے بعد، جو ایک نقطے کے ذریعے بیان کیا گیا ہے اور متن کی پوزیشن نمبر 6 پر موجود کردار سے میل کھاتا ہے۔
Matcher
چیک کرے گا کہ آیا متن باقی پیٹرن سے میل کھاتا ہے - "а
" حرف۔ -
چونکہ متن میں پیٹرن کے ساتھ کوئی مماثلت نہیں ملی (ٹیکسٹ میں پوزیشن نمبر 7 پر علامت "" ہے
л
)،Matcher
یہ پیٹرن میں ایک اور "کوئی بھی حرف" شامل کرتا ہے، کیونکہ اس کی وضاحت ایک یا زیادہ بار کی گئی ہے، اور دوبارہ پیٹرن کا موازنہ نمبر 5 سے نمبر 8 والی پوزیشنوں پر متن کے ساتھ کرتا ہے: -
ہمارے معاملے میں، ایک میچ ملا، لیکن متن کا اختتام ابھی تک نہیں پہنچا ہے. اس لیے، پوزیشن نمبر 9 سے، چیک اسی طرح کے الگورتھم کا استعمال کرتے ہوئے پیٹرن کے پہلے کریکٹر کو تلاش کرکے شروع ہوتا ہے اور پھر متن کے اختتام تک دہرایا جاتا ہے۔
main
ٹیمپلیٹ " А.+?а
" کا استعمال کرتے وقت، ہمیں درج ذیل نتیجہ ملے گا: Alla Alexa جیسا کہ ہماری مثال سے دیکھا جا سکتا ہے، جب ایک ہی ٹیمپلیٹ کے لیے مختلف کوانٹیفائر طریقوں کا استعمال کرتے ہوئے، ہمیں مختلف نتائج ملے۔ اس لیے ضروری ہے کہ اس فیچر کو مدنظر رکھا جائے اور سرچ کے دوران مطلوبہ نتائج کے لحاظ سے مطلوبہ موڈ کا انتخاب کیا جائے۔
ریگولر ایکسپریشنز میں کرداروں سے فرار
چونکہ جاوا میں ایک ریگولر ایکسپریشن، یا زیادہ واضح طور پر اس کی ابتدائی نمائندگی، سٹرنگ لٹریل کا استعمال کرتے ہوئے بیان کی گئی ہے، اس لیے ضروری ہے کہ جاوا تصریح کے قواعد کو مدنظر رکھا جائے جو اسٹرنگ لٹریلز سے متعلق ہیں۔ خاص طور پر،\
جاوا سورس کوڈ میں سٹرنگ لٹریلز میں بیک سلیش کریکٹر " " کو ایک فرار کردار سے تعبیر کیا جاتا ہے جو کمپائلر کو متنبہ کرتا ہے کہ اس کی پیروی کرنے والا کریکٹر ایک خاص کریکٹر ہے اور اس کی تشریح ایک خاص طریقے سے ہونی چاہیے۔ مثال کے طور پر:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
لہٰذا، سٹرنگ لٹریلز میں جو باقاعدہ اظہار کی وضاحت کرتے ہیں اور " \
" کیریکٹر کا استعمال کرتے ہیں (مثال کے طور پر، میٹا کریکٹرز کے لیے)، اسے دوگنا ہونا چاہیے تاکہ جاوا بائیک کوڈ کمپائلر اس کی مختلف تشریح نہ کرے۔ مثال کے طور پر:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
اگر ہم ان کو "باقاعدہ" حروف کے طور پر استعمال کرنے کا ارادہ رکھتے ہیں تو ڈبل بیک سلیش کریکٹر کو خصوصی حروف سے بچنے کے لیے بھی استعمال کیا جانا چاہیے۔ مثال کے طور پر:
String regex = "How\\?"; // template for searching the string "How?"
پیٹرن کلاس کے طریقے
کلاس کےPattern
پاس ریگولر ایکسپریشنز کے ساتھ کام کرنے کے دوسرے طریقے ہیں: String pattern()
- ریگولر ایکسپریشن کی اصل سٹرنگ کی نمائندگی لوٹاتا ہے جس سے آبجیکٹ بنایا گیا تھا Pattern
:
Pattern pattern = Pattern.compile("abc");
System.out.println(Pattern.pattern())//"abc"
static boolean matches(String regex, CharSequence input)
- آپ کو پیرامیٹر میں پاس کردہ متن کے خلاف ریجیکس پیرامیٹر میں پاس کردہ ریگولر ایکسپریشن کو چیک کرنے کی اجازت دیتا ہے input
۔ واپسی: درست - اگر متن پیٹرن سے میل کھاتا ہے؛ غلط - دوسری صورت میں؛ مثال:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()
- flags
ٹیمپلیٹ پیرامیٹر کی قدریں لوٹاتا ہے جو اس وقت سیٹ کی گئی تھیں جب اسے بنایا گیا تھا، یا 0 اگر یہ پیرامیٹر سیٹ نہیں کیا گیا تھا۔ مثال:
Pattern pattern = Pattern.compile("abc");
System.out.println(pattern.flags());// 0
Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
System.out.println(pattern.flags());// 2
String[] split(CharSequence text, int limit)
- پیرامیٹر کے بطور پاس کردہ متن کو عناصر کی ایک صف میں تقسیم کرتا ہے String
۔ پیرامیٹر limit
ان مماثلتوں کی زیادہ سے زیادہ تعداد کا تعین کرتا ہے جنہیں متن میں تلاش کیا جاتا ہے:
- جب
limit>0
-limit-1
میچوں کی تلاش کی جاتی ہے۔ - at
limit<0
- متن میں تمام مماثلتوں کو تلاش کرتا ہے۔ - جب
limit=0
- متن میں تمام مماثلتوں کو تلاش کرتا ہے، جبکہ صف کے آخر میں خالی لائنوں کو ضائع کر دیا جاتا ہے۔
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("\\s");
String[] strings = pattern.split(text,2);
for (String s : strings) {
System.out.println(s);
}
System.out.println("---------");
String[] strings1 = pattern.split(text);
for (String s : strings1) {
System.out.println(s);
}
}
کنسول آؤٹ پٹ: ایگور اللہ انا -------- ایگور اللہ اناMatcher
ہم ذیل میں آبجیکٹ بنانے کے لیے ایک اور کلاس طریقہ پر غور کریں گے۔
میچر کلاس کے طریقے
Matcher
ایک ایسی کلاس ہے جہاں سے پیٹرن تلاش کرنے کے لیے کوئی چیز بنائی جاتی ہے۔ Matcher
- یہ ایک "سرچ انجن" ہے، ریگولر ایکسپریشنز کا ایک "انجن"۔ تلاش کرنے کے لیے، اسے دو چیزیں دینے کی ضرورت ہے: ایک تلاش کا نمونہ اور ایک "پتہ" تلاش کرنے کے لیے۔ کسی چیز کو بنانے کے لیے، Matcher
کلاس میں درج ذیل طریقہ فراہم کیا جاتا ہے Pattern
: рublic Matcher matcher(CharSequence input)
ایک دلیل کے طور پر، طریقہ حروف کی ایک ترتیب لیتا ہے جس میں تلاش کی جائے گی۔ یہ کلاسز کی اشیاء ہیں جو انٹرفیس کو نافذ کرتی ہیں CharSequence
۔ String
آپ نہ صرف پاس کر سکتے ہیں بلکہ , StringBuffer
, StringBuilder
اور بطور دلیل Segment
بھی CharBuffer
۔ سرچ ٹیمپلیٹ کلاس آبجیکٹ ہے Pattern
جس پر طریقہ کہا جاتا ہے matcher
۔ میچر بنانے کی مثال:
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
اب، اپنے "سرچ انجن" کی مدد سے ہم مماثلتیں تلاش کر سکتے ہیں، متن میں مماثلت کی پوزیشن معلوم کر سکتے ہیں، اور کلاس کے طریقوں کا استعمال کرتے ہوئے متن کو تبدیل کر سکتے ہیں۔ طریقہ boolean find()
پیٹرن کے ساتھ متن میں اگلا میچ تلاش کرتا ہے۔ اس طریقہ کار اور لوپ آپریٹر کا استعمال کرتے ہوئے، آپ ایونٹ کے ماڈل کے مطابق پورے متن کا تجزیہ کر سکتے ہیں (جب کوئی واقعہ پیش آئے تو ضروری کارروائیاں کریں - متن میں مماثلت تلاش کرنا)۔ مثال کے طور پر، اس کلاس کے طریقوں کا استعمال کرتے ہوئے، int start()
آپ int end()
متن میں مماثلت کی پوزیشنوں کا تعین کر سکتے ہیں، اور طریقوں کا استعمال کرتے ہوئے String replaceFirst(String replacement)
، String replaceAll(String replacement)
متن میں موجود میچوں کو دوسرے متبادل متن سے بدل سکتے ہیں۔ مثال:
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("A.+?a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int start=matcher.start();
int end=matcher.end();
System.out.println("Match found" + text.substring(start,end) + " с "+ start + " By " + (end-1) + "position");
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Olga"));
System.out.println(text);
}
پروگرام آؤٹ پٹ: 5 سے 8 پوزیشنوں تک ایک میچ ملا ملا انا 10 سے 13 پوزیشنوں تک ایگور ایرا انا ایگور اولگا اولگا ایگور اللہ انا مثال سے واضح ہے کہ طریقے ایک نئی چیز replaceFirst
بناتے ہیں - ایک تار، جو وہ ماخذ متن ہے جس میں ٹیمپلیٹ کے ساتھ مماثلت کو دلیل کے طور پر طریقہ کو بھیجے گئے متن سے بدل دیا جاتا ہے۔ مزید یہ کہ یہ طریقہ صرف پہلے میچ اور ٹیسٹ کے تمام میچوں کی جگہ لے لیتا ہے۔ اصل متن میں کوئی تبدیلی نہیں ہے۔ دیگر طبقاتی طریقوں کا استعمال ، نیز باقاعدہ اظہار کی مثالیں، مضامین کی اس سیریز میں دیکھی جا سکتی ہیں ۔ ٹیکسٹ کے ساتھ کام کرتے وقت ریگولر ایکسپریشنز کے ساتھ سب سے زیادہ عام آپریشنز کلاسز سے ہوتے ہیں اور میں شامل ہوتے ہیں ۔ یہ طریقے ہیں جیسے , , , . لیکن حقیقت میں، "ہڈ کے نیچے" وہ استعمال کرتے ہیں اور . لہذا، اگر آپ کو غیر ضروری کوڈ لکھے بغیر کسی پروگرام میں متن کو تبدیل کرنے یا تاروں کا موازنہ کرنے کی ضرورت ہے تو، کے طریقے استعمال کریں ۔ اگر آپ کو اعلی درجے کی صلاحیتوں کی ضرورت ہے، تو کلاسز اور . replaceAll
String
replaceFirst
replaceAll
Matcher
Pattern
Matcher
String
split
matches
replaceFirst
replaceAll
Pattern
Matcher
String
Pattern
Matcher
نتیجہ
ایک ریگولر ایکسپریشن کو جاوا پروگرام میں اسٹرنگز کا استعمال کرتے ہوئے بیان کیا جاتا ہے جو قواعد کے ذریعے بیان کردہ پیٹرن سے میل کھاتا ہے۔ جب کوڈ چلتا ہے، جاوا اس سٹرنگ کو کلاس آبجیکٹ میں دوبارہ کمپائل کرتا ہےPattern
اور کلاس آبجیکٹ کو Matcher
ٹیکسٹ میں میچز تلاش کرنے کے لیے استعمال کرتا ہے۔ جیسا کہ میں نے شروع میں کہا، باقاعدہ اظہار کو اکثر بعد کے لیے ایک طرف رکھ دیا جاتا ہے، جسے ایک مشکل موضوع سمجھا جاتا ہے۔ تاہم، اگر آپ نحو کی بنیادی باتوں کو سمجھتے ہیں، میٹاکریکٹرز، فرار، اور ریگولر ایکسپریشنز کی مثالوں کا مطالعہ کرتے ہیں، تو وہ اس سے کہیں زیادہ آسان نکلتے ہیں جتنا کہ پہلی نظر میں لگتا ہے۔
GO TO FULL VERSION