কেন "আসাদেফ"? স্থান (/.*/ জি, "এক্স") == "এক্সএক্স"?


129

আমি একটি আশ্চর্যজনক (আমার কাছে) সত্যকে সামনে রেখে হোঁচট খেয়েছি।

console.log("asdf".replace(/.*/g, "x"));

কেন দুটি প্রতিস্থাপন? দেখে মনে হচ্ছে যে নিউলাইনগুলি ছাড়াই খালি খালি স্ট্রিং এই প্যাটার্নটির জন্য ঠিক দুটি প্রতিস্থাপন তৈরি করবে। একটি প্রতিস্থাপন ফাংশন ব্যবহার করে, আমি দেখতে পাচ্ছি যে প্রথম প্রতিস্থাপনটি পুরো স্ট্রিংয়ের জন্য এবং দ্বিতীয়টি খালি স্ট্রিংয়ের জন্য।


9
আরও সাধারণ উদাহরণ: "asdf".match(/.*/g)ফিরে ["এসএসডিএফ", ""]
ন্যারো

32
বিশ্বব্যাপী (ছ) পতাকার কারণে। পূর্ববর্তী ম্যাচ শেষে বিশ্বব্যাপী পতাকাটি অন্য অনুসন্ধান শুরু করার অনুমতি দেয়, সুতরাং খালি স্ট্রিংটি খুঁজে পাওয়া যায়।
সেলসিয়াস

6
এবং সৎ হতে দিন: সম্ভবত কেউই ঠিক সেই আচরণটি চায়নি। এটি সম্ভবত অনুপস্থিত একটি বাস্তবায়ন বিস্তারিত ছিল "aa".replace(/b*/, "b")ফলে babab। এবং এক পর্যায়ে আমরা ওয়েব ব্রাউজারগুলির সমস্ত বাস্তবায়ন বিবরণকে মানিক করে দিয়েছি।
লাক্স

4
জিএনইউ সেডের জোশুয়া পুরানো সংস্করণগুলি (অন্যান্য বাস্তবায়ন নয়!) এছাড়াও এই বাগ প্রদর্শন করছে, এটি 2.05 এবং 3.01 রিলিজের (20+ বছর পূর্বে) কোথাও স্থির করা হয়েছিল। আমি সন্দেহ করি সেখানেই এই আচরণের উত্স ছিল, পার্লে যাওয়ার আগে (যেখানে এটি একটি বৈশিষ্ট্য হয়ে উঠেছে) এবং সেখান থেকে জাভাস্ক্রিপ্টে প্রবেশ করানো।
মশবী

1
@ রিসার্সিভ - যথেষ্ট ভাল। আমি তাদের উভয়ই এক সেকেন্ডের জন্য অবাক করে দেখি, তারপরে "শূন্য-প্রস্থের ম্যাচ" উপলব্ধি করে আর আর অবাক হই না। :-)
টিজে ক্রোডার

উত্তর:


98

অনুযায়ী ECMA-262 মান String.prototype.replace আহ্বান RegExp.prototype [@@ প্রতিস্থাপন] , যা বলে:

11. Repeat, while done is false
  a. Let result be ? RegExpExec(rx, S).
  b. If result is null, set done to true.
  c. Else result is not null,
    i. Append result to the end of results.
    ii. If global is false, set done to true.
    iii. Else,
      1. Let matchStr be ? ToString(? Get(result, "0")).
      2. If matchStr is the empty String, then
        a. Let thisIndex be ? ToLength(? Get(rx, "lastIndex")).
        b. Let nextIndex be AdvanceStringIndex(S, thisIndex, fullUnicode).
        c. Perform ? Set(rx, "lastIndex", nextIndex, true).

যেখানে rxহয় /.*/gএবং Sহয় 'asdf'

11.c.iii.2.b দেখুন:

খ। নেক্সটইন্ডেক্সকে অ্যাডভান্সস্ট্রিংইন্ডেক্স (এস, এটিআইডেক্স, ফুল ইউনিকোড) হতে দিন।

সুতরাং 'asdf'.replace(/.*/g, 'x')এটি আসলে:

  1. ফলাফল ( []অপরিজ্ঞাত ), ফলাফল = , সর্বশেষ তালিকা =0
  2. ফলাফল = 'asdf', ফলাফলগুলি = [ 'asdf' ], সর্বশেষ তালিকা =4
  3. ফলাফলের = '', ফলাফল = [ 'asdf', '' ], lastIndex = 4, AdvanceStringIndex, lastIndex সেট5
  4. ফলাফল = null, ফলাফল = [ 'asdf', '' ], প্রত্যাবর্তন

সুতরাং 2 টি ম্যাচ আছে।


42
এই উত্তরটি বুঝতে আমার এটি পড়াশোনা করা দরকার।
ফিলিপ

টিএল; ডিআর এটি মেলা 'asdf'এবং খালি স্ট্রিং ''
জিমঃ

34

একসাথে ইয়াওকাতের সাথে অফলাইনে চ্যাটে আমরা কেন দুটি ম্যাচ হুবহু উত্পাদন করে তা দেখার একটি স্বজ্ঞাত উপায় খুঁজে পেয়েছি "abcd".replace(/.*/g, "x")। নোট করুন যে আমরা ECMAScript স্ট্যান্ডার্ড দ্বারা আরোপিত শব্দার্থবিজ্ঞানের সম্পূর্ণরূপে সমান কিনা তা পরীক্ষা করে দেখিনি, তাই কেবল এটি থাম্বের নিয়ম হিসাবে গ্রহণ করুন।

চলতি নিয়ম

  • ম্যাচগুলিকে (matchStr, matchIndex)কালানুক্রমিক ক্রমের তালিকার তালিকা হিসাবে বিবেচনা করুন যা ইঙ্গিত দেয় যে ইনপুট স্ট্রিংয়ের স্ট্রিং অংশগুলি এবং সূচকগুলি ইতিমধ্যে খেয়েছে।
  • এই তালিকাটি নিয়মিতভাবে ইনজেক্ট স্ট্রিংয়ের বাম থেকে শুরু করে রেগেক্সের জন্য নির্মিত।
  • ইতিমধ্যে খেয়ে নেওয়া অংশগুলি আর মেলে না
  • প্রতিস্থাপনটি সেই অবস্থানে matchIndexথাকা স্ট্রিংগুলিকে ওভাররাইট করে প্রদত্ত সূচকগুলিতে করা হয় matchStr। যদি matchStr = "", তবে "প্রতিস্থাপন" কার্যকরভাবে সন্নিবেশ করা হয়।

আনুষ্ঠানিকভাবে, মিলে যাওয়া এবং প্রতিস্থাপনের কাজটিকে অন্যান্য উত্তরে যেমন দেখানো হয় তেমন একটি লুপ হিসাবে বর্ণনা করা হয় ।

সহজ উদাহরণ

  1. "abcd".replace(/.*/g, "x")ফলাফল "xx":

    • ম্যাচের তালিকাটি হ'ল [("abcd", 0), ("", 4)]

      উল্লেখযোগ্যভাবে, এটি নিম্নলিখিত ম্যাচগুলিকে অন্তর্ভুক্ত করে না যা নিম্নলিখিত কারণগুলির কারণে কেউ ভাবতে পারে:

      • ("a", 0), ("ab", 0): কোয়ান্টিফায়ার *লোভী
      • ("b", 1), ("bc", 1): পূর্ববর্তী ম্যাচের কারণে ("abcd", 0), স্ট্রিংগুলি "b"এবং "bc"ইতিমধ্যে খেয়ে ফেলেছে
      • ("", 4), ("", 4) (অর্থাত্ দ্বিগুণ): সূচক অবস্থান 4 ইতিমধ্যে প্রথম আপাত ম্যাচ দ্বারা খেয়ে ফেলেছে
    • অত: পর, প্রতিস্থাপন স্ট্রিং "x"ঠিক সেই অবস্থানে এ পাওয়া ম্যাচে স্ট্রিং প্রতিস্থাপন: অবস্থান 0 এ স্ট্রিং প্রতিস্থাপন "abcd"এবং অবস্থান 4 এ প্রতিস্থাপন ""

      এখানে আপনি দেখতে পাচ্ছেন যে প্রতিস্থাপনটি পূর্ববর্তী স্ট্রিংয়ের সত্যিকারের প্রতিস্থাপন বা নতুন স্ট্রিংয়ের সন্নিবেশ হিসাবে কাজ করতে পারে।

  2. "abcd".replace(/.*?/g, "x")একটি অলস কোয়ান্টিফায়ার*? আউটপুট সঙ্গে"xaxbxcxdx"

    • ম্যাচের তালিকাটি হ'ল [("", 0), ("", 1), ("", 2), ("", 3), ("", 4)]

      পূর্ববর্তী উদাহরণে বিপরীতে, এখানে ("a", 0), ("ab", 0), ("abc", 0), অথবা এমনকি ("abcd", 0)কোয়ান্টিফায়ার এর আলস্য যে কঠোরভাবে সীমিত এটা সম্ভাব্য স্বল্পতম মিল খুঁজে কারণে অন্তর্ভুক্ত হয় না।

    • যেহেতু সমস্ত ম্যাচের স্ট্রিং খালি রয়েছে, কোনও প্রকৃত প্রতিস্থাপন ঘটে না, তবে x0, 1, 2, 3, এবং 4 অবস্থানগুলিতে সন্নিবেশ ।

  3. "abcd".replace(/.+?/g, "x")একটি অলস কোয়ান্টিফায়ার+? আউটপুট সঙ্গে"xxxx"

    • ম্যাচের তালিকাটি হ'ল [("a", 0), ("b", 1), ("c", 2), ("d", 3)]
  4. "abcd".replace(/.{2,}?/g, "x")একটি অলস কোয়ান্টিফায়ার[2,}? আউটপুট সঙ্গে"xx"

    • ম্যাচের তালিকাটি হ'ল [("ab", 0), ("cd", 2)]
  5. "abcd".replace(/.{0}/g, "x")"xaxbxcxdx"উদাহরণ 2 হিসাবে একই যুক্তি দ্বারা আউটপুট ।

আরও কঠোর উদাহরণ

আমরা যদি সর্বদা একটি খালি স্ট্রিংয়ের সাথে মেলে এবং এমন অবস্থানগুলি যেখানে আমাদের সুবিধার সাথে ঘটে তখন অবস্থানটি নিয়ন্ত্রণ করি তবে আমরা প্রতিস্থাপনের পরিবর্তে সন্নিবেশকরণের ধারণাকে ধারাবাহিকভাবে কাজে লাগাতে পারি । উদাহরণস্বরূপ, আমরা খালি স্ট্রিংয়ের সাথে মিল রেখে নিয়মিত এক্সপ্রেশন তৈরি করতে পারি এখানে এমনকি একটি অক্ষর সন্নিবেশ করতে:

  1. "abcdefgh".replace(/(?<=^(..)*)/g, "_"))একটি সঙ্গে ইতিবাচক lookbehind(?<=...) আউটপুট "_ab_cd_ef_gh_"(শুধুমাত্র এতদূর Chrome এ সমর্থিত)

    • ম্যাচের তালিকাটি হ'ল [("", 0), ("", 2), ("", 4), ("", 6), ("", 8)]
  2. "abcdefgh".replace(/(?=(..)*$)/g, "_"))একটি ইতিবাচক চেহারা(?=...) আউটপুট সঙ্গে"_ab_cd_ef_gh_"

    • ম্যাচের তালিকাটি হ'ল [("", 0), ("", 2), ("", 4), ("", 6), ("", 8)]

4
আমি মনে করি এটিকে স্বজ্ঞাগত বলার জন্য এটি কিছুটা প্রসারিত (এবং সাহসের সাথে বলতে হবে)। আমার কাছে এটি দেখতে আরও স্টকহোম সিন্ড্রোম এবং উত্তর-পরের যৌক্তিকরণের মতো। আপনার উত্তরটি ভাল, বিটিডাব্লু, আমি কেবল জেএস ডিজাইনের বিষয়ে অভিযোগ করি, বা সেই বিষয়ে ডিজাইনের অভাব।
এরিক ডুমিনিল

7
@ এরিকডুমিনিল আমি প্রথমেও তাই ভেবেছিলাম, তবে উত্তরটি লেখার পরে স্কেচড গ্লোবাল-রেজেক্স-রিপ্লেস অ্যালগরিদমটি মনে হয় যে কোনওটি স্ক্র্যাচ থেকে শুরু করলে এটি ঠিক যেভাবে সামনে আসে। এটা মত while (!input not eaten up) { matchAndEat(); }। এছাড়াও, উপরের মন্তব্যগুলি ইঙ্গিত দেয় যে আচরণটি জাভাস্ক্রিপ্টের অস্তিত্বের অনেক আগে থেকেই উদ্ভূত হয়েছিল।
কমফ্রিচ

2
যে অংশটি এখনও বোধগম্য হয় না ("স্ট্যান্ডার্ড যা বলে তার চেয়ে অন্য কোনও কারণে") চারটি অক্ষরের ম্যাচটি ("abcd", 0)4 অবস্থানটি খায় না যেখানে নীচের অক্ষরটি যাবে, তবুও শূন্য-চরিত্রের ম্যাচটি ("", 4)করে নিম্নলিখিত চরিত্রটি যেখানে যেতে 4 অবস্থানটি খাবেন। যদি আমি এটি স্ক্র্যাচ থেকে ডিজাইন করছিলাম তবে আমি মনে করি যে আমি যে নিয়মটি ব্যবহার করব তা হল iff (str2, ix2)অনুসরণ করতে পারে , যা এই অপব্যবহারের কারণ নয়। (str1, ix1)ix2 >= ix1 + str1.length() && ix2 + str2.length() > ix1 + str1.length()
অ্যান্ডারস ক্যাসরগ

2
@ আন্ডারস ক্যাসরগ ("abcd", 0)4 পজিশ "abcd"লম্বা পজিশন খায় না এবং তাই 0, 1, 2, 3 সূচকগুলি খায় your আপনার যুক্তিটি কোথা থেকে আসতে পারে তা আমি দেখতে পাচ্ছি: কেন আমরা ("abcd" ⋅ ε, 0)5-চরিত্রের দীর্ঘ ম্যাচ হিসাবে থাকতে পারি না যেখানে ⋅ সংমিশ্রণ এবং εশূন্য প্রস্থের ম্যাচ? সাধারণত কারণ "abcd" ⋅ ε = "abcd"। আমি শেষ মুহুর্তের জন্য একটি স্বজ্ঞাত কারণ সম্পর্কে ভেবেছিলাম, তবে এটির সন্ধান করতে ব্যর্থ হয়েছি। আমি অনুমান করি যে একজনকে সর্বদা εকেবল নিজের মতো ঘটনাক্রমে আচরণ করা উচিত ""আমি সেই বাগ বা কীর্তি ছাড়াই বিকল্প প্রয়োগের সাথে খেলতে চাই,
কমফ্রিচ

1
যদি চারটি অক্ষরের স্ট্রিংটিতে চারটি সূচক খাওয়া উচিত হয় তবে শূন্যের অক্ষরের স্ট্রিংটিতে কোনও সূচক না খাওয়া উচিত। আপনি যে কোনও যুক্তিটি তৈরি করতে পারেন তা অন্যের সাথে সমানভাবে প্রয়োগ করা উচিত (উদাহরণস্বরূপ "" ⋅ ε = "", যদিও আপনি নিশ্চিত নন যে আপনি কোন পার্থক্যটি আঁকতে চান ""এবং εযার অর্থ একই জিনিস)। সুতরাং পার্থক্যটি স্বজ্ঞাত হিসাবে ব্যাখ্যা করা যায় না — এটি কেবল সহজ।
অ্যান্ডারস কাসের্গ

26

প্রথম ম্যাচটি অবশ্যই "asdf"(অবস্থান [0,4])। বিশ্বব্যাপী পতাকাটি ( g) সেট করা থাকায় এটি অনুসন্ধান চালিয়ে যায়। এই মুহুর্তে (পজিশন 4) এটি একটি দ্বিতীয় ম্যাচ, একটি খালি স্ট্রিং (অবস্থান [4,4]) সন্ধান করে।

মনে রাখবেন যে *শূন্য বা আরও বেশি উপাদানের সাথে মেলে।


4
তাহলে তিনটি ম্যাচ হবে না কেন? শেষে আর একটি খালি ম্যাচ হতে পারে। ঠিক আছে দুটি। এই ব্যাখ্যাটি ব্যাখ্যা করে যে সেখানে দুটি কেন হতে পারে তবে কেন এক বা তিনটির পরিবর্তে সেখানে থাকতে হবে তা নয়।
পুনরাবৃত্তি

7
না, অন্য খালি স্ট্রিং নেই। কারণ সেই খালি স্ট্রিংটি পাওয়া গেছে। 4,4 অবস্থানের উপর একটি খালি স্ট্রিং, এটি একটি অনন্য ফলাফল হিসাবে সনাক্ত করা হয়েছে। "4,4" লেবেলযুক্ত একটি ম্যাচ পুনরাবৃত্তি করা যাবে না। সম্ভবত আপনি ভাবতে পারেন যে [0,0] পজিশনে একটি খালি স্ট্রিং রয়েছে তবে * অপারেটর উপাদানগুলির সর্বাধিক সম্ভব প্রদান করে। এই কারণেই কেবল 4,4 সম্ভব
ডেভিড এসকে

16
আমাদের মনে রাখতে হবে রেজেক্সগুলি নিয়মিত প্রকাশ নয়। নিয়মিত অভিব্যক্তিগুলিতে, প্রতি দুটি চরিত্রের পাশাপাশি শুরুতে এবং শেষে অনেকগুলি ফাঁকা স্ট্রিং থাকে। রেজেক্সে, রেগেক্স ইঞ্জিনের নির্দিষ্ট গন্ধের স্পেসিফিকেশন হিসাবে ঠিক অনেকগুলি খালি স্ট্রিং রয়েছে।
জার্গ ডব্লু মিত্তাগ

7
এটি কেবলমাত্র উত্তর-পরে যুক্তিযুক্তকরণ।
মশবী

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