কেন বিশ্বব্যাপী পতাকা সহ একটি রেজইপেক্স ভুল ফলাফল দেয়?


277

আমি যখন বিশ্বব্যাপী পতাকা এবং কেস সংবেদনশীল পতাকা ব্যবহার করি তখন এই নিয়মিত প্রকাশে সমস্যাটি কী? ক্যোয়ারী একটি ব্যবহারকারী উত্পন্ন ইনপুট। ফলাফলটি [সত্য, সত্য] হওয়া উচিত।

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
result.push(re.test('Foo Bar'));
// result will be [true, false]

var reg = /^a$/g;
for(i = 0; i++ < 10;)
   console.log(reg.test("a"));


54
জাভাস্ক্রিপ্টে RegExp এর অনেকগুলি ফাঁদে একটিতে আপনাকে স্বাগতম। অদ্ভুত পার্শ্ব-প্রতিক্রিয়া এবং অস্পষ্ট সতর্কবাণীতে পূর্ণ, রেগেক্স প্রসেসিংয়ের এটির মধ্যে সবচেয়ে খারাপ ইন্টারফেস রয়েছে। আপনি সাধারণত রেইগেক্সের সাথে করতে চান এমন সাধারণ কাজগুলির বেশিরভাগই সঠিক বানান করা কঠিন।
বোবিন্স

এক্সরেগএক্সপ্স একটি ভাল বিকল্পের মতো দেখায়। xregexp.com
প্রায়

: এখানে পাশাপাশি উত্তর দেখার stackoverflow.com/questions/604860/...
Prestaul

একটি সমাধান, যদি আপনি এটি থেকে দূরে সরে যেতে পারেন, তা হ'ল রেগেক্স আক্ষরিক এটি এটিকে সংরক্ষণ করার পরিবর্তে সরাসরি ব্যবহার করা re
thdoan

উত্তর:


350

RegExpবস্তুর ট্র্যাক রাখে lastIndexযেখানে একটি ম্যাচ ঘটেছে, তাই পরবর্তী ম্যাচ তে এটি সর্বশেষ ব্যবহৃত সূচক থেকে শুরু হবে, 0. পরিবর্তে দেখে নিন:

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));

alert(re.lastIndex);

result.push(re.test('Foo Bar'));

আপনি যদি lastIndexপ্রতিটি পরীক্ষার পরে ম্যানুয়ালি 0 এ পুনরায় সেট করতে না চান তবে কেবল gপতাকাটি সরিয়ে ফেলুন ।

চশমাগুলি নির্দেশ করে এমন অ্যালগরিদম এখানে রয়েছে (বিভাগ 15.10.6.2):

RegExp.prototype.exec (STRING)

নিয়মিত অভিব্যক্তির বিরুদ্ধে স্ট্রিংয়ের একটি নিয়মিত এক্সপ্রেশন ম্যাচ সম্পাদন করে এবং ম্যাচের ফলাফলগুলি সহ একটি অ্যারে অবজেক্ট ফেরত দেয় বা স্ট্রিংটি মেলে না তা হলে স্ট্রিং টোস্ট্রিং (স্ট্রিং) নিয়মিত এক্সপ্রেশন প্যাটার্নের ঘটনার জন্য অনুসন্ধান করা হয়:

  1. এসকে ToString (স্ট্রিং) এর মান হতে দিন।
  2. দৈর্ঘ্য এস এর দৈর্ঘ্য হতে দিন।
  3. লাস্ট ইন্ডেক্সকে লাস্ট ইন্ডেক্সের সম্পত্তি হতে দেওয়া উচিত।
  4. আসুন আমি ToInteger (সর্বশেষ তালিকা) এর মান হতে পারি।
  5. বিশ্বব্যাপী সম্পত্তিটি যদি মিথ্যা হয় তবে আসুন আমি = 0 করি।
  6. আমি <0 বা I> দৈর্ঘ্য হলে লাস্ট ইনডেক্স 0 এ সেট করে নাল ফিরে আসি।
  7. এস এবং আই যুক্তি দিয়ে এটি [[ম্যাচ]] কল করুন। [[ম্যাচ]] ব্যর্থতা ফিরে পেলে, আট ধাপে যান; অন্যথায় এর রাজ্যের ফলাফল হতে দিন এবং 10 ধাপে যান।
  8. I = i + 1 দিন।
  9. Step ধাপে যান।
  10. আসুন r এর অন্তিমূলক মান হতে দিন।
  11. বিশ্বব্যাপী সম্পত্তিটি সত্য হলে ইস্টের সর্বশেষ তালিকাটি সেট করুন।
  12. এন এর ক্যাপচার অ্যারে দৈর্ঘ্য হতে দিন। (এটি 15.10.2.1 এর NCapturingParens এর সমান মান))
  13. নিম্নলিখিত বৈশিষ্ট্য সহ একটি নতুন অ্যারে ফেরত দিন:
    • সূচক বৈশিষ্ট্যটি সম্পূর্ণ স্ট্রিং এস এর সাথে মিলিত সাবস্ট্রিংয়ের অবস্থানে সেট করা আছে
    • ইনপুট সম্পত্তি সেট করা হয়েছে এস।
    • দৈর্ঘ্যের বৈশিষ্ট্যটি n + 1 এ সেট করা আছে।
    • 0 টি বৈশিষ্ট্যটি ম্যাচটি করা স্ট্রিংয়ে সেট করা হয়েছে (অর্থাত্ অফসেট i সমেত এবং অফসেট এবং এক্সক্লুসিভের মধ্যে এস এর অংশ)।
    • প্রতিটি পূর্ণসংখ্যার জন্য যেমন আমি> 0 এবং আমি ≤ n, তোস্ট্রিং (i) নামের সম্পত্তিটিকে r এর ক্যাপচার অ্যারের আইথ উপাদানটিতে সেট করে।

83
এটি এখানে গ্যালাক্সি এপিআই ডিজাইনের জন্য হিচিকারের গাইডের মতো। "আপনি যে পতনের মধ্যে পড়েছিলেন তা বেশ কয়েক বছর
ধরেই সেই অনুমানের

5
ফায়ারফক্সের স্টিকি ফ্ল্যাগটি আপনাকে যা বোঝায় তা তেমন করে না। বরং এটি এমনভাবে কাজ করে যা নিয়মিত প্রকাশের শুরুতে একটি were ছিল, EXCEPT যে এটি of স্ট্রিং শুরুর চেয়ে বর্তমান স্ট্রিং পজিশনের (লাস্ট ইনডেক্স) সাথে মেলে। আপনি কার্যকরভাবে পরীক্ষা করে দেখছেন যে "লাস্ট ইনডেক্সের পরে কোথাও" এর পরিবর্তে রেজেক্স "ঠিক এখানে" মিলছে। আপনার সরবরাহিত লিঙ্কটি দেখুন!
Doin থেকে

1
এই উত্তরের খোলার বিবৃতি ঠিক সঠিক নয়। আপনি অনুমানের 3 ধাপ হাইলাইট করেছেন যা কিছুই বলে না। আসল প্রভাবটি lastIndex5, 6 এবং 11 পদক্ষেপে রয়েছে opening বিশ্বব্যাপী পতাকাটি সেট করা থাকলে আপনার খোলার বক্তব্যটি কেবলমাত্র সত্য।
Prestaul

@ প্রসৌল হ্যাঁ, আপনি ঠিক বলেছেন যে এটি বিশ্বব্যাপী পতাকাটির কথা উল্লেখ করে না। প্রশ্নটি যেভাবে তৈরি করা হয়েছে তার কারণেই সম্ভবত এটি ছিল (আমি কী বলেছিলাম তা মনে করতে পারি না)। উত্তরটি সম্পাদন করতে বা এটি মোছার জন্য নির্দ্বিধায় এবং আপনার উত্তরের সাথে লিঙ্ক করুন। এছাড়াও, আমি আপনাকে আশ্বস্ত করি যে আপনি আমার চেয়ে ভাল। উপভোগ করুন!
আয়নু জি স্টান

@ আইয়নুজি.স্ট্যান, দুঃখিত যদি আমার আগের মন্তব্যটি আক্রমণাত্মক মনে হয়, তবে এটি আমার উদ্দেশ্য ছিল না। আমি এই মুহুর্তে এটি সম্পাদনা করতে পারি না, তবে আমি আমার মন্তব্যের প্রয়োজনীয় বিষয়টির দিকে দৃষ্টি আকর্ষণ করার জন্য চিৎকার করার চেষ্টা করছিলাম না। আমার খারাপ!
প্রেস্টাউল

72

আপনি একটি একক RegExpঅবজেক্ট ব্যবহার করছেন এবং একাধিকবার এটি কার্যকর করছেন। প্রতিটি ক্রমাগত কার্যকরকরণের ক্ষেত্রে এটি শেষ ম্যাচ সূচী থেকে অব্যাহত থাকে।

প্রতিটি মৃত্যুদন্ড কার্যকর করার আগে আপনাকে প্রথম থেকেই শুরু করতে "রিসেট" করতে হবে:

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
// result is now [true, true]

এটি বলেছিলেন যে প্রতিবারই নতুন রেজিপ এক্সপেক্ট তৈরি করা আরও পঠনযোগ্য হতে পারে (যেভাবেই RegExp ক্যাশে থাকায় ওভারহেড ন্যূনতম হয়):

result.push((/Foo B/gi).test(stringA));
result.push((/Foo B/gi).test(stringB));

1
অথবা কেবল gপতাকা ব্যবহার করবেন না ।
melpomene

36

RegExp.prototype.testনিয়মিত প্রকাশের lastIndexসম্পত্তি আপডেট করে যাতে প্রতিটি পরীক্ষা যেখানে শেষ হয় সেখানে থামবে will আমি String.prototype.matchএটি ব্যবহার করার পরামর্শ দিচ্ছি কারণ এটি lastIndexসম্পত্তি আপডেট করে না :

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true

দ্রষ্টব্য: !!এটিকে বুলিয়ানতে রূপান্তর করে এবং তারপরে বুলিয়ানকে উল্টে দেয় যাতে ফলাফলটি প্রতিফলিত হয়।

বিকল্পভাবে, আপনি কেবল lastIndexসম্পত্তি পুনরায় সেট করতে পারেন :

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));

11

গ্লোবাল gপতাকা সরানো আপনার সমস্যার সমাধান করবে।

var re = new RegExp(query, 'gi');

হতে হবে

var re = new RegExp(query, 'i');

0

আপনাকে re.lastIndex = 0 সেট করতে হবে কারণ জি ফ্ল্যাগ রেজেক্সের সাহায্যে সর্বশেষ ম্যাচটি দেখা যায়, সুতরাং পরীক্ষা একই স্ট্রিংটি পরীক্ষা করতে যায় না, এজন্য আপনাকে পুনরায় তালিকাভুক্ত করতে হবে = 0

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
re.lastIndex=0;
result.push(re.test('Foo Bar'));

console.log(result)


-1

/ জি পতাকা ব্যবহার করে এটি হিটের পরে অনুসন্ধান চালিয়ে যেতে বলে।

যদি ম্যাচটি সফল হয় তবে এক্সিকিউট () পদ্ধতিটি একটি অ্যারে প্রদান করে এবং নিয়মিত এক্সপ্রেশন অবজেক্টের বৈশিষ্ট্য আপডেট করে।

আপনার প্রথম অনুসন্ধানের আগে:

myRegex.lastIndex
//is 0

প্রথম অনুসন্ধানের পরে

myRegex.lastIndex
//is 8

ছাগুলি সরান এবং এটি প্রতিটি কল সম্পাদনের জন্য () সম্পাদনের পরে অনুসন্ধান থেকে প্রস্থান করে।


ওপি ব্যবহার করছে না exec
melpomene

-1

আমি ফাংশন ছিল:

function parseDevName(name) {
  var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
  var match = re.exec(name);
  return match.slice(1,4);
}

var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");

প্রথম কলটি কাজ করে। দ্বিতীয় কল আসে না। sliceঅপারেশন একটি নাল মান সম্পর্কে অভিযোগ। আমি ধরে নিলাম এটি কারণ re.lastIndex। এটি আশ্চর্যজনক কারণ আমি RegExpপ্রতিবার ফাংশনটি ডাকা হলেও আমার ফাংশনের একাধিক আহবান জুড়ে ভাগ না করে একটি নতুন বরাদ্দের আশা করব।

আমি যখন এটিকে পরিবর্তন করেছি:

var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');

তারপরে আমি lastIndexহোল্ডওভার এফেক্টটি পাই না । এটি যেমনটি আশা করি তেমন কাজ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.