programing

작은따옴표 또는 큰따옴표로 둘러싸여 있지 않은 경우 공백을 사용하여 문자열을 분할하기 위한 정규식

javaba 2022. 11. 5. 11:28
반응형

작은따옴표 또는 큰따옴표로 둘러싸여 있지 않은 경우 공백을 사용하여 문자열을 분할하기 위한 정규식

저는 정규 표현은 처음이라 잘 부탁드립니다.단일 따옴표 또는 이중 따옴표로 둘러싸여 있지 않은 모든 공간을 사용하여 예제 문자열을 분할하는 식을 조합하려고 합니다.(?!")제대로 작동하지 않습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

입력 예:

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'띄띄

왜 다른 사람들이 그렇게 복잡한 정규 표현식이나 긴 코드를 제안하는지 이해할 수 없다.기본적으로 문자열에서 두 가지 항목을 가져옵니다. 공백이나 따옴표가 아닌 문자의 순서와 따옴표 없이 따옴표로 시작하고 끝나는 문자의 순서입니다.다음 정규 표현식을 사용하면 이러한 항목을 쉽게 일치시킬 수 있습니다.

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

목록에서 인용문을 원하지 않기 때문에 캡처 그룹을 추가했습니다.

이 Java 코드는 목록을 작성하고 따옴표를 제외하기 위해 일치하는 경우 캡처 그룹을 추가하고, 따옴표가 없는 단어가 일치하면 전체 regex 일치를 추가합니다.

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());
} 

StackOverflow에는 정규 표현을 사용하는 다양한 컨텍스트에서 이 같은 질문을 다루는 몇 가지 질문이 있습니다.예:

업데이트: 단일 따옴표로 묶인 문자열과 이중 따옴표로 묶인 문자열을 처리하는 예제 regex입니다.참조: 안쪽 따옴표를 사용하지 않고 문자열로 분할하려면 어떻게 해야 합니까?

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

이를 빠른 Perl 스니펫으로 테스트하여 다음과 같이 출력했습니다.따옴표 사이에 있는 빈 문자열이나 공백 전용 문자열에도 사용할 수 있습니다(원하는 문자열인지 아닌지 확실하지 않음).

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

일치하는 값에 따옴표 문자 자체가 포함되지만 문자열 치환으로 따옴표를 제거하거나 따옴표를 포함하지 않도록 regex를 수정할 수 있습니다.지금은 독자나 다른 포스터를 위한 연습으로 남겨두겠습니다.오전 2시는 정규 표현을 망치기에는 너무 늦기 때문입니다.

문자열 내에서 이스케이프 따옴표를 허용하려면 다음과 같이 사용할 수 있습니다.

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

따옴표로 묶인 문자열은 그룹 2, 따옴표로 묶이지 않은 단일 단어는 그룹 3이 됩니다.

http://www.fileformat.info/tool/regex.htm 또는 http://gskinner.com/RegExr/ 에서 다양한 문자열로 시도하실 수 있습니다.

Jan Goyvaerts의 regex는 지금까지 발견된 솔루션 중 가장 좋은 솔루션이지만 빈(null) 일치도 생성하며, 그는 이를 프로그램에서 제외합니다.이러한 빈 일치는 regex 테스터(rubular.com 등)에서도 표시됩니다.검색을 정렬할 경우(먼저 따옴표로 묶인 부분과 공백 구분 단어보다 먼저 검색) 다음과 같이 한 번에 수행할 수 있습니다.

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

이 값은 큰따옴표로 둘러싸지 않은 공간과 일치합니다.Java는 *와 +를 지원하지 않기 때문에 min,max {0,9999}을(를) 사용해야 합니다.

각 부분을 잡는 것이 분할하는 것보다 끈을 찾는 것이 더 쉬울 것입니다.

때문에 수 ."will be"다만, 분할내의 간격을 무시하도록 지정할 수 있는 방법이 생각나지 않습니다.

(실제 Java가 아님)

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"

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."

Marcus의 접근법이 마음에 들었지만, 인용문 근처에 텍스트를 넣을 수 있도록 수정하여 "와 "를 모두 지원하도록 했습니다.예를 들어, [a=, "some value"]로 분할하지 않으려면 a="some value"가 필요했습니다.

(?<!\\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"

Jan의 접근법은 훌륭하지만 여기 공식적으로 다른 방법이 있다.

된 바와 분할하고 를 그대로 합니다."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

c# 를 사용하고 있는 경우는,

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]*)>"를 클릭하여 그룹화할 문자를 지정할 수 있음을 강조 표시합니다.(이 경우는,< > 를 사용해 그룹화합니다.

출력은 다음과 같습니다.

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

String.split()을 사용한 첫 번째 원라이너

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자, 오른쪽에 있는 모든 문자가 단일 따옴표도 이중 따옴표도 아닌 경우 공백으로 분할됩니다.

원래 투고에서 개작(큰따옴표만 포함)

정규 표현만으로는 불가능하다고 확신합니다.다른 태그에 어떤 것이 포함되어 있는지 확인하는 것은 해석 작업입니다.이것은 정규식을 사용하여 XML을 구문 분석하는 것과 같은 문제인 것처럼 보입니다.정확하게 해석할 수 없습니다.인용된 문자열과 일치하는 비권한, 비글로벌 정규식을 반복 적용하면 원하는 결과를 얻을 수 있습니다. 그리고 다른 항목을 찾을 수 없으면 공백에서 분할하십시오.모든 서브스트링의 원래 순서를 추적하는 등 여러 가지 문제가 있습니다.가장 좋은 방법은 문자열을 반복하고 원하는 토큰을 꺼내는 매우 간단한 함수를 쓰는 것입니다.

Jan이 받아들인 답변에 대해 몇 가지 도움이 되기를 바랍니다.

(['"])((?:\\\1|.)+?)\1|([^\s"']+)
  • 따옴표로 묶인 문자열 내에서 이스케이프 따옴표를 허용합니다.
  • 단일 따옴표와 이중 따옴표 패턴을 반복하지 않습니다.또한 필요에 따라 견적 기호를 추가할 수 있습니다(캡처 그룹을 하나 더 추가).

다음의 조작도 실행할 수 있습니다.

    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]);
        }
    }

다음은 인수 배열을 반환합니다.인수는 단일 따옴표 또는 이중 따옴표에 포함되지 않는 한 공백으로 분할된 변수 '명령어'입니다.그런 다음 단일 따옴표와 이중 따옴표를 삭제하도록 일치가 수정됩니다.

using System.Text.RegularExpressions;

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

언급URL : https://stackoverflow.com/questions/366202/regex-for-splitting-a-string-using-space-when-not-surrounded-by-single-or-double

반응형