একক বা ডাবল উদ্ধৃতি দ্বারা চারপাশে না থাকলে স্পেস ব্যবহার করে স্ট্রিংকে বিভক্ত করার জন্য রেজেক্স


114

আমি নিয়মিত প্রকাশে নতুন এবং আপনার সাহায্যের প্রশংসা করব। আমি এক সাথে একটি ভাব প্রকাশ করার চেষ্টা করছি যা একক বা ডাবল উদ্ধৃতি দ্বারা ঘেরা না এমন সমস্ত স্থান ব্যবহার করে উদাহরণের স্ট্রিংটিকে বিভক্ত করবে। আমার শেষ প্রয়াসটি এরকম দেখাচ্ছে: (?!")এবং বেশ কার্যকর নয়। এটি উদ্ধৃতি দেওয়ার আগে স্পেসে বিভক্ত হয়ে গেছে।

উদাহরণ ইনপুট:

This is a string that "will be" highlighted when your 'regular expression' matches something.

পছন্দসই আউটপুট:

This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something.

এটি লক্ষ্য করুন "will be"এবং 'regular expression'শব্দের মধ্যে স্থান বজায় রাখুন ।


আপনি কি আসলে "বিভক্ত" পদ্ধতিটি ব্যবহার করছেন, বা ম্যাচারের উপর "ফাইন্ড" পদ্ধতিটি লুপিং যথেষ্ট?
ইরিকসন

9
"এবং এখন তার দুটি সমস্যা আছে"

উত্তর:


251

আমি বুঝতে পারছি না কেন অন্যরা কেন এইরকম জটিল নিয়মিত প্রকাশ বা এত দীর্ঘ কোডের প্রস্তাব দিচ্ছেন। মূলত, আপনি আপনার স্ট্রিং থেকে দুটি ধরণের জিনিস হস্তান্তর করতে চান: অক্ষরগুলির ক্রম যা শূন্যস্থান বা উদ্ধৃতি নয়, এবং অক্ষরের ক্রমগুলি যেগুলি শুরু হয় এবং একটি উদ্ধৃতি দিয়ে শেষ হয়, উভয় প্রকারের উদ্ধৃতি হিসাবে between আপনি এই নিয়মিত প্রকাশের সাথে সহজেই সেই জিনিসগুলির সাথে মেলে ফেলতে পারেন:

[^\s"']+|"([^"]*)"|'([^']*)'

আমি ক্যাপচারিং গ্রুপগুলি যুক্ত করেছি কারণ আপনি তালিকায় কোটগুলি চান না।

এই জাভা কোডটি তালিকাটি তৈরি করে, ক্যাপচারিং গ্রুপটি কোটগুলি বাদ দেওয়ার সাথে মিলে যায় এবং ক্যাপচারিং গ্রুপটি মেলে না তবে সামগ্রিক রেজেক্স ম্যাচ যুক্ত করে (একটি অব্যক্ত শব্দটির সাথে মেলে)।

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    if (regexMatcher.group(1) != null) {
        // Add double-quoted string without the quotes
        matchList.add(regexMatcher.group(1));
    } else if (regexMatcher.group(2) != null) {
        // Add single-quoted string without the quotes
        matchList.add(regexMatcher.group(2));
    } else {
        // Add unquoted word
        matchList.add(regexMatcher.group());
    }
} 

যদি আপনি ফিরে আসা তালিকায় উদ্ধৃতিগুলি রাখতে আপত্তি না করেন তবে আপনি আরও সহজ কোড ব্যবহার করতে পারেন:

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    matchList.add(regexMatcher.group());
} 

1
জান, আপনার প্রতিক্রিয়া জন্য ধন্যবাদ। বিটিডাব্লু, আমি এডিটপ্যাডের একটি বড় অনুরাগী।
carlsz

আমি যদি স্ট্রিংগুলিতে পালিয়ে থাকা উক্তিগুলির অনুমতি দিতে চাই \"?
মন্টিওর

3
এই উত্তরের সমস্যাটি তুলনাহীন John's mother[John, s, mother]
উক্তিটির

2
ইস্যু leonbloy প্রান্তরেখা সমাধানের জন্য, আপনি পুনরায়-অর্ডার করতে পারেন operands একটি বিট এবং হোয়াইটস্পেস-গ্রুপ থেকে কোট বর্জন: "([^"]*)"|'([^']*)'|[^\s]+
ঘোস্টকিপার

1
এটি এবং অন্যান্য উত্তর উপর নির্মাণের নিম্নলিখিত Regex কোট ভিতরে অক্ষর পলায়নের অনুমতি দেয়: "([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+। দেখুন stackoverflow.com/questions/5695240/...
Limnic

15

স্ট্যাকওভারফ্লোতে বেশ কয়েকটি প্রশ্ন রয়েছে যা নিয়মিত প্রকাশের সাহায্যে বিভিন্ন প্রসঙ্গে এই একই প্রশ্নটি কভার করে। এই ক্ষেত্রে:

আপডেট : একক এবং ডাবল উদ্ধৃত স্ট্রিংগুলি পরিচালনা করতে নমুনা রেজেক্স। রেফ: উত্তরের ভিতরে থাকা ছাড়া আমি কীভাবে স্ট্রিনে বিভক্ত হতে পারি?

m/('.*?'|".*?"|\S+)/g 

একটি দ্রুত পার্ল স্নিপেটের সাথে এটি পরীক্ষিত হয়েছিল এবং আউটপুট নীচে পুনরুত্পাদন করা হয়েছিল। খালি স্ট্রিং বা হোয়াইটস্পেস-শুধুমাত্র স্ট্রিংগুলির জন্য কাজ করে যদি সেগুলি উদ্ধৃতিগুলির মধ্যে থাকে (নিশ্চিত না যে এটি পছন্দ করেছে কিনা)।

This
is
a
string
that
"will be"
highlighted
when
your
'regular expression'
matches
something.

নোট করুন যে এতে কোট অক্ষরগুলি মিলে যাওয়া মানগুলিতে অন্তর্ভুক্ত রয়েছে যদিও আপনি স্ট্রিংয়ের সাহায্যে এটি মুছে ফেলতে পারেন, বা রেজেক্সকে অন্তর্ভুক্ত না করে পরিবর্তন করতে পারেন। আমি এখনই পাঠকের জন্য বা অন্য পোস্টারের অনুশীলন হিসাবে ছেড়ে দেব, যেহেতু সকাল 2 টা আর নিয়মিত প্রকাশের সাথে বিশৃঙ্খলা করতে দেরি হচ্ছে;)


আমি মনে করি আপনার রেজেক্সটি মেলানো কোটকে মঞ্জুরি দেয়, যেমন "হবে" এবং "নিয়মিত এক্সপ্রেশন"।
জাচ স্ক্রিভেনা

@ জাচ - আপনি ঠিকই বলেছেন, ঠিকঠাক ক্ষেত্রে এটি ঠিক করার জন্য এটি আপডেট করেছে
জে

6

আপনি যদি স্ট্রিংয়ের মধ্যে পালিয়ে থাকা উক্তিগুলির অনুমতি দিতে চান তবে আপনি এই জাতীয় কিছু ব্যবহার করতে পারেন:

(?:(['"])(.*?)(?<!\\)(?>\\\\)*\1|([^\s]+))

উদ্ধৃত স্ট্রিংগুলি গ্রুপ 2 হবে, একক অব্যক্ত শব্দগুলি গ্রুপ 3 হবে।

আপনি এখানে বিভিন্ন স্ট্রিং এ এটি ব্যবহার করতে পারেন: http://www.fileformat.info/tool/regex.htm বা http://gskinner.com/RegExr/


3

জান গোয়েভার্টসের কাছ থেকে পাওয়া রেজিেক্স হ'ল আমি এ পর্যন্ত পাওয়া সেরা সমাধান, তবে খালি (নাল) ম্যাচও তৈরি করে, যা সে তার প্রোগ্রামে বাদ দেয়। এই খালি ম্যাচগুলি রেজেক্স পরীক্ষকদের (যেমন রুবুলার ডটকম) থেকেও উপস্থিত হয়। যদি আপনি অনুসন্ধানগুলি চারদিকে ঘুরে দেখেন (প্রথমে উদ্ধৃত অংশগুলি এবং স্পেস সেপারড শব্দের চেয়ে সন্ধান করুন) তবে আপনি এটি একবারে এটি করতে পারেন:

("[^"]*"|'[^']*'|[\S]+)+

2
(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s

এটি ডাবল উদ্ধৃতি দ্বারা ঘেরাও না এমন জায়গাগুলির সাথে মিলবে। আমাকে ন্যূনতম, সর্বোচ্চ {0,99999 use ব্যবহার করতে হবে কারণ জাভা * এবং + চেহারাটির পিছনে সমর্থন করে না।


1

স্ট্রিংটি অনুসন্ধান করা সহজ হবে, প্রতিটি অংশকে দখল করে, বনাম বিভক্ত করুন।

কারণ হওয়ার কারণে, আপনি এটি আগে এবং পরে ফাঁকা জায়গায় বিভক্ত করতে পারেন "will be"। তবে, আমি কোনও বিভক্তির অভ্যন্তরের স্থানটিকে উপেক্ষা করে নির্দিষ্ট করার কোনও উপায় সম্পর্কে ভাবতে পারি না।

(প্রকৃত জাভা নয়)

string = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";

regex = "\"(\\\"|(?!\\\").)+\"|[^ ]+"; // search for a quoted or non-spaced group
final = new Array();

while (string.length > 0) {
    string = string.trim();
    if (Regex(regex).test(string)) {
        final.push(Regex(regex).match(string)[0]);
        string = string.replace(regex, ""); // progress to next "word"
    }
}

এছাড়াও, একক উদ্ধৃতি ক্যাপচার সমস্যার কারণ হতে পারে:

"Foo's Bar 'n Grill"

//=>

"Foo"
"s Bar "
"n"
"Grill"

আপনার সমাধানটি একক-উদ্ধৃত স্ট্রিংগুলি পরিচালনা করে না, যা কার্লের উদাহরণের অংশ।
জান গোয়েভার্টস

1

String.split()এখানে সহায়ক নয় কারণ উদ্ধৃতিগুলির মধ্যে স্থানগুলি (বিভক্ত করবেন না) এবং বাইরের (বিভক্ত) এর মধ্যে পার্থক্য করার কোনও উপায় নেই। Matcher.lookingAt()আপনার প্রয়োজন সম্ভবত:

String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
str = str + " "; // add trailing space
int len = str.length();
Matcher m = Pattern.compile("((\"[^\"]+?\")|('[^']+?')|([^\\s]+?))\\s++").matcher(str);

for (int i = 0; i < len; i++)
{
    m.region(i, len);

    if (m.lookingAt())
    {
        String s = m.group(1);

        if ((s.startsWith("\"") && s.endsWith("\"")) ||
            (s.startsWith("'") && s.endsWith("'")))
        {
            s = s.substring(1, s.length() - 1);
        }

        System.out.println(i + ": \"" + s + "\"");
        i += (m.group(0).length() - 1);
    }
}

যা নিম্নলিখিত আউটপুট উত্পাদন করে:

0: "This"
5: "is"
8: "a"
10: "string"
17: "that"
22: "will be"
32: "highlighted"
44: "when"
49: "your"
54: "regular expression"
75: "matches"
83: "something."

1

আমি মার্কসের এই পদ্ধতির পছন্দ করি, তবে আমি এটিকে সংশোধন করেছিলাম যাতে আমি উদ্ধৃতিগুলির নিকটে পাঠ্যকে অনুমতি দিতে পারি এবং "এবং 'উক্ত অক্ষর উভয়কেই সমর্থন করতে পারি example উদাহরণস্বরূপ, এটিকে [a =," বিভক্ত না করার জন্য আমার একটি = "কিছু মান" প্রয়োজন needed কিছু মান "]।

(?<!\\G\\S{0,99999}[\"'].{0,99999})\\s|(?<=\\G\\S{0,99999}\".{0,99999}\"\\S{0,99999})\\s|(?<=\\G\\S{0,99999}'.{0,99999}'\\S{0,99999})\\s"

1

জান এর পদ্ধতির দুর্দান্ত তবে রেকর্ডের জন্য এখানে অন্য একটি।

শিরোনামে উল্লিখিত আপনি আসলে বিভক্ত করতে চেয়েছিলেন, কোট পালন "will be"এবং 'regular expression', তাহলে আপনি এই পদ্ধতি যার সোজা আউট ব্যবহার করতে পারে ম্যাচ একটি প্যাটার্ন S1, S2, S3 ইত্যাদি পরিস্থিতিতে ছাড়া (অথবা প্রতিস্থাপন)

রেজেক্স:

'[^']*'|\"[^\"]*\"|( )

দুটি বাম প্রান্তিক সম্পূর্ণ 'quoted strings'এবং "double-quoted strings"। আমরা এই ম্যাচগুলিকে উপেক্ষা করব। ডান দিকটি গ্রুপ 1 এ স্পেসগুলি মেলে এবং ক্যাপচার করে এবং আমরা জানি যে এগুলি সঠিক স্থান কারণ তারা বাম দিকের অভিব্যক্তিগুলির সাথে মিলে নি। SplitHereতারপরে যাদের বিভক্ত হয় তাদের আমরা প্রতিস্থাপন করি SplitHere। আবার এটি সত্যিকারের বিভাজনের ক্ষেত্রে যেখানে আপনি চান সেখানে "will be"নয় will be

এখানে একটি পূর্ণ কার্যকারিতা বাস্তবায়ন ( অনলাইন ডেমোতে ফলাফল দেখুন )।

import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.util.List;

class Program {
public static void main (String[] args) throws java.lang.Exception  {

String subject = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
Pattern regex = Pattern.compile("\'[^']*'|\"[^\"]*\"|( )");
Matcher m = regex.matcher(subject);
StringBuffer b= new StringBuffer();
while (m.find()) {
    if(m.group(1) != null) m.appendReplacement(b, "SplitHere");
    else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
String[] splits = replaced.split("SplitHere");
for (String split : splits) System.out.println(split);
} // end main
} // end Program

1

আপনি যদি সি # ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন

string input= "This is a string that \"will be\" highlighted when your 'regular expression' matches <something random>";

List<string> list1 = 
                Regex.Matches(input, @"(?<match>\w+)|\""(?<match>[\w\s]*)""|'(?<match>[\w\s]*)'|<(?<match>[\w\s]*)>").Cast<Match>().Select(m => m.Groups["match"].Value).ToList();

foreach(var v in list1)
   Console.WriteLine(v);

আপনি গ্রুপ বাক্যাংশে যে কোনও চরিত্র নির্দিষ্ট করতে পারবেন তা হাইলাইট করতে আমি " | <(? [\ W \ s] *)> " বিশেষভাবে যুক্ত করেছি । (এই ক্ষেত্রে আমি <> গ্রুপে ব্যবহার করছি using

আউটপুট হল:

This
is
a
string
that
will be
highlighted
when
your
regular expression 
matches
something random

0

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


একটি রেইজেক্সের মাধ্যমে এটি সম্ভব, আমি সংযুক্ত কয়েকটি নমুনা দেখুন। এটিতে কয়েকটি ভিন্নতা রয়েছে এবং আমি এসও তে বেশ কয়েকটি অনুরূপ প্রশ্ন দেখেছি যা নিয়মিত প্রকাশের মাধ্যমে এটিকে সম্বোধন করে।
জে

1
জেনে নিন কখন রেজেক্স ব্যবহার করবেন না এটি আরও সহায়ক জ্ঞান তাহলে একটি (?: (([''))) (। *?) (? <! \) (?> \\\) * \ 1 | ([[ ^ \ s] +))
রিনি

0

এক দম্পতি আশা করি জ্যানের গৃহীত উত্তরের জন্য টুইটগুলি:

(['"])((?:\\\1|.)+?)\1|([^\s"']+)
  • উদ্ধৃত স্ট্রিংয়ের মধ্যে পালিয়ে থাকা উদ্ধৃতিগুলিকে অনুমতি দেয়
  • একক এবং ডাবল উদ্ধৃতি জন্য প্যাটার্ন পুনরাবৃত্তি এড়ানো; এটি প্রয়োজনে আরও উদ্ধৃতি প্রতীক যুক্ত করা সহজতর করে (আরও একটি ক্যাপচারিং গ্রুপের ব্যয়ে)

এটি তাদের মধ্যে অ্যাস্ট্রোফেসের সাথে শব্দগুলি ভেঙে দেয়, যেমনyou're
এড্রিয়ান

0

আপনি এটি ব্যবহার করে দেখতে পারেন:

    String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something";
    String ss[] = str.split("\"|\'");
    for (int i = 0; i < ss.length; i++) {
        if ((i % 2) == 0) {//even
            String[] part1 = ss[i].split(" ");
            for (String pp1 : part1) {
                System.out.println("" + pp1);
            }
        } else {//odd
            System.out.println("" + ss[i]);
        }
    }

এটি কেন কাজ করা উচিত সে সম্পর্কে আপনার সত্যিই কিছু ব্যাখ্যা যুক্ত করা উচিত - আপনি কোডটি কোডের পাশাপাশি কোডটিতেও মন্তব্যগুলি যুক্ত করতে পারেন - বর্তমান রূপে এটি কোনও ব্যাখ্যা সরবরাহ করে না যা সম্প্রদায়ের বাকী অংশগুলি কী বুঝতে সাহায্য করতে পারে আপনি প্রশ্নের সমাধান / উত্তর দিতে চেয়েছিলেন। ইতিমধ্যে উত্তর রয়েছে এমন প্রশ্নের জন্য এটি বিশেষত গুরুত্বপূর্ণ।
ishmaelMakitla

0

নিম্নলিখিতটি আর্গুমেন্টের অ্যারে দেয়। যুক্তিগুলি হ'ল স্থানগুলিতে পরিবর্তনশীল 'কমান্ড' বিভাজন, যদি না একক বা ডাবল উদ্ধৃতি অন্তর্ভুক্ত থাকে। ম্যাচগুলি তারপরে একক এবং ডাবল উদ্ধৃতিগুলি সরানোর জন্য পরিবর্তন করা হয়।

using System.Text.RegularExpressions;

var args = Regex.Matches(command, "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'").Cast<Match>
().Select(iMatch => iMatch.Value.Replace("\"", "").Replace("'", "")).ToArray();

2
আপনি কি নিজের উত্তরে কিছুটা ব্যাখ্যা যোগ করতে পারেন যাতে অন্যরা সহজেই তা বুঝতে পারে? আদর্শভাবে আমরা কোড-কেবল উত্তরগুলি এড়াতে চাই।
জাকজ

0

স্ট্রিং.স্প্লিট () ব্যবহার করে 1 ম লাইনার

String s = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
String[] split = s.split( "(?<!(\"|').{0,255}) | (?!.*\\1.*)" );

[This, is, a, string, that, "will be", highlighted, when, your, 'regular expression', matches, something.]

ফাঁকাটি একক বা ডাবল উদ্ধৃতি দ্বারা বেষ্টিত থাকলে ফাঁকা জায়গায় বিভক্ত করবেন না
ফাঁকা হয়ে থাকে যখন বিভক্ত হয় যখন বাম দিকে 255 টি অক্ষর এবং ফাঁকের ডানদিকে সমস্ত অক্ষর একক না ডাবল উদ্ধৃতি হয়

মূল পোস্ট থেকে অভিযোজিত (কেবলমাত্র ডাবল উদ্ধৃতিগুলি পরিচালনা করে)

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