আমি কীভাবে জাভাস্ক্রিপ্টে রেজেক্স লিটারেলগুলি সংযুক্ত করতে পারি?


145

এরকম কিছু করা কি সম্ভব?

var pattern = /some regex segment/ + /* comment here */
    /another segment/;

অথবা আমার কি নতুন RegExp()সিনট্যাক্স ব্যবহার করতে হবে এবং একটি স্ট্রিং যুক্ত করতে হবে? কোডটি আরও স্ব-স্পষ্ট এবং সংক্ষিপ্ত উভয় হওয়ায় আমি আক্ষরিক ব্যবহার করতে পছন্দ করব।


2
আপনি যদি স্ট্রিং.আরও () ব্যবহার করেন তবে পালিয়ে যাওয়া রেজেক্স চরিত্রগুলির সাথে কাজ করা আরও সহজ:let regexSegment1 = String.raw`\s*hello\s*`
iono

উত্তর:


190

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

var segment_part = "some bit of the regexp";
var pattern = new RegExp("some regex segment" + /*comment here */
              segment_part + /* that was defined just now */
              "another segment");

আপনার যদি দুটি নিয়মিত অভিব্যক্তি আক্ষরিক হয়, তবে আপনি এই কৌশলটি ব্যবহার করে বাস্তবে তাদেরকে সম্মতি জানাতে পারেন:

var regex1 = /foo/g;
var regex2 = /bar/y;
var flags = (regex1.flags + regex2.flags).split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
var regex3 = new RegExp(expression_one.source + expression_two.source, flags);
// regex3 is now /foobar/gy

এটি আক্ষরিক নিয়মিত প্রকাশের পরিবর্তে কেবল দুটি এবং আক্ষরিক স্ট্রিং হিসাবে প্রকাশের চেয়ে আরও স্পষ্ট।


2
এই পদ্ধতিটি ব্যবহার করার সময় প্রতিটি বিভাগ অবশ্যই একটি বৈধ নিয়মিত অভিব্যক্তি হতে হবে তা মনে রাখবেন। যেমন একটি অভিব্যক্তি নির্মাণ new RegExp(/(/.source + /.*/.source + /)?/.source);কাজ বলে মনে হচ্ছে না।
স্যাম

এই সমাধান ব্যাক-ম্যাচিং গ্রুপগুলির ক্ষেত্রে কাজ করে না। সেক্ষেত্রে কার্যক্ষম সমাধানের জন্য আমার উত্তরটি দেখুন।
মিকাউল মায়ার

আপনার যদি কোনও চর থেকে পালাতে হয়, তবে ডাবল ব্যাকস্ল্যাশগুলি ব্যবহার করুন: নতুন রেজিএক্সএক্স ('\\ $' + "ফ্লাম")
জেফ লোয়ার

আপনার যদি "<regexp> .flags" এর সাথে থাকতে হয় তবে আপনি পতাকাগুলি অ্যাক্সেস করতে পারেন, তাত্ত্বিকভাবে আপনি এগুলিও সংহত করতে পারেন।
বিন্নামক

আপনি কোথা expression_oneথেকে পাচ্ছেন ? মানে regex1?
টালঅর্ডারদেভ

30

কেবল এলোমেলোভাবে নিয়মিত এক্সপ্রেশন অবজেক্টগুলিকে কনটেন্ট করা কিছু বিরূপ পার্শ্ব প্রতিক্রিয়া হতে পারে। ব্যবহার করুন RegExp.source পরিবর্তে:

var r1 = /abc/g;
var r2 = /def/;
var r3 = new RegExp(r1.source + r2.source, 
                   (r1.global ? 'g' : '') 
                   + (r1.ignoreCase ? 'i' : '') + 
                   (r1.multiline ? 'm' : ''));
console.log(r3);
var m = 'test that abcdef and abcdef has a match?'.match(r3);
console.log(m);
// m should contain 2 matches

এটি আপনাকে স্ট্যান্ডার্ড RegExp ফ্ল্যাগগুলি ব্যবহার করে আগের রেজিএক্সপ্যাক্স থেকে নিয়মিত প্রকাশের পতাকা ধরে রাখার ক্ষমতাও দেবে।

jsFiddle


এটি ব্যবহার করে উন্নতি করা যেতে পারেRegExp.prototype.flags
দিমিত্রি পার্জিটস্কি

19

আমি "ইভাল" বিকল্পের সাথে একমত হই না।

var xxx = /abcd/;
var yyy = /efgh/;
var zzz = new RegExp(eval(xxx)+eval(yyy));

"// abcd // efgh //" দেবে যা উদ্দিষ্ট ফলাফল নয়।

মত উত্স ব্যবহার

var zzz = new RegExp(xxx.source+yyy.source);

"/ abcdefgh /" দেবে এবং এটি সঠিক।

যৌক্তিক মূল্যায়ন করার দরকার নেই, আপনি নিজের এক্সপ্রেশনটি জানেন। আপনার কেবল এটির উত্স প্রয়োজন বা এটি কীভাবে লেখা হয় এটির প্রয়োজনীয়তার প্রয়োজন নেই। পতাকাগুলি হিসাবে, আপনার কেবল RegExp এর alচ্ছিক যুক্তি ব্যবহার করা উচিত।

আমার পরিস্থিতিতে, আমি একসাথে একত্রিত করার চেষ্টা করছি এমন একাধিক অভিব্যক্তিতে ^ এবং $ ব্যবহৃত হওয়ার ইস্যুতে আমি চালিয়ে যাচ্ছি! এই এক্সপ্রেশনগুলি প্রোগ্রামার জুড়ে ব্যবহৃত ব্যাকরণ ফিল্টার। PREPOSITIONS কেস পরিচালনা করতে এখন আমি তাদের কয়েকটি ব্যবহার করতে চাই না। প্রারম্ভিক এবং শেষ ^ (এবং / অথবা) remove :) অপসারণের জন্য আমাকে উত্সগুলি "টুকরা" করতে হতে পারে Che :) চিয়ার্স, অ্যালেক্স।


আমি উত্স-সম্পত্তি ব্যবহার পছন্দ করি। আপনি যদি - আমার মতো - jslint ব্যবহার করেন তবে আপনি যদি এই জাতীয় কিছু করেন তবে তা জোর করে:var regex = "\.\..*"
নিলস-ও-ম্যাট

7

সমস্যা যদি রেজিপ্সে back 1 এর মতো ব্যাক-ম্যাচিং গ্রুপ থাকে।

var r = /(a|b)\1/  // Matches aa, bb but nothing else.
var p = /(c|d)\1/   // Matches cc, dd but nothing else.

তারপরে কেবল উত্সকে বিদ্রূপ করা কার্যকর হবে না। প্রকৃতপক্ষে, দুজনের সংমিশ্রণটি হ'ল:

var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false

সমাধান: প্রথমে আমরা প্রথম রেজেক্সে ম্যাচের গ্রুপগুলির সংখ্যা গণনা করি, তারপরে দ্বিতীয়টিতে প্রতিটি ব্যাক-ম্যাচিং টোকেনের জন্য, আমরা এটি মিলে যাওয়া গ্রুপগুলির সংখ্যা দ্বারা বৃদ্ধি করি।

function concatenate(r1, r2) {
  var count = function(r, str) {
    return str.match(r).length;
  }
  var numberGroups = /([^\\]|^)(?=\((?!\?:))/g; // Home-made regexp to count groups.
  var offset = count(numberGroups, r1.source);    
  var escapedMatch = /[\\](?:(\d+)|.)/g;        // Home-made regexp for escaped literals, greedy on numbers.
  var r2newSource = r2.source.replace(escapedMatch, function(match, number) { return number?"\\"+(number-0+offset):match; });
  return new RegExp(r1.source+r2newSource,
      (r1.global ? 'g' : '') 
      + (r1.ignoreCase ? 'i' : '')
      + (r1.multiline ? 'm' : ''));
}

টেস্ট:

var rp = concatenate(r, p) // returns  /(a|b)\1(c|d)\2/
rp.test("aadd") // Returns true

2
হ্যাঁ (যদিও আমি এটি এখানে পরিবর্তন করব না)। এই ফাংশনটি function concatenateList() { var res = arguments[0]; for(var i = 1; i < arguments.length; i++) { res = concatenate(res, arguments[i]); } return res; }
সম্মোহিত

3

আক্ষরিক সিনট্যাক্স যতবার সম্ভব ব্যবহার করা ভাল। এটি খাটো, আরও সুস্পষ্ট এবং আপনার পলায়নের উদ্ধৃতি বা ডাবল-পলায়ন ব্যাকল্যাশগুলির প্রয়োজন নেই। "জাভাস্ক্রিপ্ট প্যাটার্নস", স্টোয়ান স্টেফানভ ২০১০ থেকে।

তবে নতুন ব্যবহার করা একমাত্র উপায় হতে পারে aten

আমি avoid এটা নিরাপদ নয়.


1
আমি মনে করি জটিল নিয়মিত এক্সপ্রেশনগুলি আরও সুস্পষ্ট হয় যখন প্রশ্নটির মতোই ভেঙে যায় এবং মন্তব্য করা হয়।
স্যাম

3

যে সরবরাহ করে:

  • আপনি জানেন যে আপনি আপনার রিজেক্সেপে কী করেন;
  • প্যাটার্ন গঠনে আপনার কাছে অনেকগুলি রেগেক্স টুকরা রয়েছে এবং তারা একই পতাকা ব্যবহার করবে;
  • আপনার ছোট প্যাটার্ন খণ্ডগুলিকে একটি অ্যারেতে আলাদা করা আপনার পক্ষে আরও পঠনযোগ্য বলে মনে হয়;
  • আপনি পরবর্তী দেব বা নিজের জন্য পরে প্রতিটি অংশে মন্তব্য করতে সক্ষম হতে চান;
  • আপনি /this/gবরং আপনার রেজেক্সের চেয়ে দৃশ্যত সরল করতে পছন্দ করেনnew RegExp('this', 'g') ;
  • আপনার প্রথম থেকেই এক টুকরো টুকরো করে রাখার চেয়ে অতিরিক্ত পদক্ষেপে রেজেক্সটি একত্রিত করা ঠিক আছে;

তাহলে আপনি এইভাবে লিখতে পছন্দ করতে পারেন:

var regexParts =
    [
        /\b(\d+|null)\b/,// Some comments.
        /\b(true|false)\b/,
        /\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|length|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/,
        /(\$|jQuery)/,
        /many more patterns/
    ],
    regexString  = regexParts.map(function(x){return x.source}).join('|'),
    regexPattern = new RegExp(regexString, 'g');

তারপরে আপনি এর মতো কিছু করতে পারেন:

string.replace(regexPattern, function()
{
    var m = arguments,
        Class = '';

    switch(true)
    {
        // Numbers and 'null'.
        case (Boolean)(m[1]):
            m = m[1];
            Class = 'number';
            break;

        // True or False.
        case (Boolean)(m[2]):
            m = m[2];
            Class = 'bool';
            break;

        // True or False.
        case (Boolean)(m[3]):
            m = m[3];
            Class = 'keyword';
            break;

        // $ or 'jQuery'.
        case (Boolean)(m[4]):
            m = m[4];
            Class = 'dollar';
            break;

        // More cases...
    }

    return '<span class="' + Class + '">' + m + '</span>';
})

আমার বিশেষ ক্ষেত্রে (একটি কোড-আয়না সদৃশ সম্পাদক), একটি এক্সপ্রেশন মোড়ানোর জন্য এইচটিএমএল ট্যাগের সাথে প্রতিবার প্রতিস্থাপনের মতো অনুসরণ করার মতো অনেকগুলি প্রতিস্থাপনের পরিবর্তে একটি বড় রেইগেক্স সম্পাদন করা অনেক সহজ, এইচটিএমএল ট্যাগ নিজেই প্রভাবিত না করে লক্ষ্য নির্ধারণ করা কঠিন (এবং দুর্ভাগ্যক্রমে জাভাস্ক্রিপ্টে সমর্থিত নয় এমন ভাল চেহারা ব্যতীত ):

.replace(/(\b\d+|null\b)/g, '<span class="number">$1</span>')
.replace(/(\btrue|false\b)/g, '<span class="bool">$1</span>')
.replace(/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/g, '<span class="keyword">$1</span>')
.replace(/\$/g, '<span class="dollar">$</span>')
.replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation">$1</span>')

2

আপনি যেমন কিছু করতে পারেন:

function concatRegex(...segments) {
  return new RegExp(segments.join(''));
}

বিভাগগুলি পৃথক যুক্তি হিসাবে পাস করা স্ট্রিংগুলি (রেজেক্স লিটারালগুলির চেয়ে বরং) হবে।


1

না, আক্ষরিক উপায় সমর্থিত নয়। আপনাকে RegExp ব্যবহার করতে হবে।


1

2 টি প্যারাম দিয়ে কনস্ট্রাক্টরটি ব্যবহার করুন এবং '/' ট্রেলিংয়ের সমস্যাটি এড়ান:

var re_final = new RegExp("\\" + ".", "g");    // constructor can have 2 params!
console.log("...finally".replace(re_final, "!") + "\n" + re_final + 
    " works as expected...");                  // !!!finally works as expected

                         // meanwhile

re_final = new RegExp("\\" + "." + "g");              // appends final '/'
console.log("... finally".replace(re_final, "!"));    // ...finally
console.log(re_final, "does not work!");              // does not work

1

আপনি আক্ষরিক এবং RegExp উভয় শ্রেণীরই থেকে রেগেক্স উত্সটি একত্রিত করতে পারেন:

var xxx = new RegExp(/abcd/);
var zzz = new RegExp(xxx.source + /efgh/.source);

1

আমার কাছে সহজ উপায়টি উত্সগুলিকে একত্রিত করা হবে, যেমন:

a = /\d+/
b = /\w+/
c = new RegExp(a.source + b.source)

সি মান এর ফলস্বরূপ হবে:

/ \ D + \ W + + /


-2

আমি ব্যবহার করতে পছন্দ করি eval('your expression')কারণ এটি /প্রতিটি প্রান্তে যুক্ত /করে ='new RegExp'না।

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