정규식에서 여러 줄의 문자를 일치시키는 방법은 무엇입니까?


356

예를 들어이 정규식

(.*)<FooBar>

일치합니다 :

abcde<FooBar>

그러나 여러 줄에서 어떻게 일치합니까?

abcde
fghij<FooBar>

1
명확히하기 위해; 원래 Eclipse를 사용하여 여러 파일에서 찾기 및 바꾸기를 수행했습니다. 아래 답변으로 발견 한 것은 내 문제가 정규식 패턴이 아니라 도구라는 것입니다.
andyuk

2
이클립스 솔루션을 찾는 사람 이이 질문을 찾은 다음 (일식처럼) 이클립스가 아닌 솔루션을 찾은 것으로 생각하기 때문에 귀하의 깃발 "일식"을 제거해야합니다.
acme 2016 년

2
이제 일식이 언급되어 있기 때문에 검색 엔진에서 이것을 찾고 있습니다. 오 공포.
Brian Olsen

답변:


240

언어에 따라 다르지만 정규식 패턴에 추가 할 수있는 수정자가 있어야합니다. PHP에서는 다음과 같습니다.

/(.*)<FooBar>/s

끝에 있는 s 는 점이 개행을 포함한 모든 문자 와 일치하게 합니다 .


내가 원하는 것을하면 바로 새로운 라인이 아닌 모든 문자를?
Grace

3
@Grace : \ n을 사용하여 줄 바꿈
Jeremy Ruten

5
적어도 Chrome / V8에서는 s 플래그가 유효하지 않습니다 (현재?). 대신 마침표 대신 / ([\ s \ S] *) <FooBar> / 문자 클래스 (공백 및 비 공백)를 사용하십시오. 자세한 내용은 다른 답변을 참조하십시오
Allen

8
@Allen-JavaScript는 s수정자를 지원하지 않습니다 . 대신 [^]*같은 효과를냅니다.
Derek 朕 會 功夫

1
Ruby에서 m수정자를 사용하십시오
Ryan Buckley

357

이 시도:

((.|\n)*)<FooBar>

기본적으로 "모든 문자 또는 줄 바꾸기"는 0 번 이상 반복되었습니다.


5
이것은 사용중인 언어 및 / 또는 도구에 따라 다릅니다. Perl, PHP, CF, C #, sed, awk 등 무엇을 사용하고 있는지 알려주십시오.
Ben Doom

39
라인 엔딩에 따라 필요할 수 있습니다((.|\n|\r)*)<FooBar>
Potherca

3
그는 이클립스를 사용하고 있다고 말했다. 이것은 내 의견으로는 올바른 해결책입니다. 나는 같은 문제가 있으며 이것이 해결되었습니다.
Danubian Sailor

4
맞습니다-질문은 일식에 관한 것이며 태그도 마찬가지입니다. 그러나 허용되는 솔루션은 PHP 솔루션입니다. 당신은 받아 들여진 해결책이어야합니다…
acme

16
이것은 여러 줄 입력을 일치시키는 데 가장 나쁜 정규식입니다. ElasticSearch를 사용하지 않는 한 절대 사용하지 마십시오. [\s\S]*또는을 사용하십시오 (?s).*.
Wiktor Stribiżew

88

문제는 어떤. 패턴과 일치 할 수 있다는 것 입니다 문자 있습니까? 답은 엔진마다 다릅니다. 주요 차이점은 패턴이 POSIX 또는 비 POSIX 정규식 라이브러리에서 사용되는지 여부입니다.

에 대한 특별 참고 사항 : 정규식으로 간주되지 않지만 .POSIX 기반 엔진과 동일한 문자와 일치합니다.

다른 메모 : .기본적으로 모든 문자와 일치합니다 ( demo ) : str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');( 항목 tokens포함 abcde\n fghij).

또한 의 정규식 문법은 기본적으로 점이 줄 바꿈과 일치합니다. Boost의 ECMAScript 문법을 사용하면 regex_constants::no_mod_m( source ) 로이 기능을 끌 수 있습니다 .

에 관해서 (POSIX 기반) n옵션 ( demo )을 사용하십시오.select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

POSIX 기반 엔진 :

단지 .이미 줄 바꿈과 일치하며 수정자를 사용할 필요가 없습니다.( 데모 ).

그만큼 ( 데모 )( 데모 )(TRE, no 기본 R 기본 엔진 perl=TRUE, stringr / stringi 패턴 이 perl=TRUE있거나 기본 R의 경우 인라인 수정자를 사용하십시오 ) ( demo )도 같은 방식으로 처리 하십시오. (?s).

그러나 대부분의 POSIX 기반 도구는 입력을 한 줄씩 처리합니다. 따라서 .범위에 속하지 않기 때문에 줄 바꿈과 일치하지 않습니다. 이를 무시하는 몇 가지 예는 다음과 같습니다.

  • -여러 가지 해결 방법이 있으며 가장 정확하지만 안전하지는 않습니다 sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'( H;1h;$!d;x;파일을 메모리에 넣습니다). 전체 줄을 포함해야하는 경우 sed '/start_pattern/,/end_pattern/d' file(시작에서 제거하면 일치하는 줄이 포함 된 것으로 끝남) 또는 sed '/start_pattern/,/end_pattern/{{//!d;};}' file(일치하는 줄을 제외하고) 고려할 수 있습니다.
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"( -0전체 파일을 메모리에 넣고,에 -p의해 제공된 스크립트를 적용한 후 파일을 인쇄합니다 -e). 을 사용 -000pe하면 파일이 문지르고 Perl이 연속 줄 바꿈 ( \n\n)을 레코드 구분 기호로 사용하는 '단락 모드'를 활성화 합니다.
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file. 여기에서 z파일 슬러 핑을 (?s)활성화하고, .패턴에 대해 DOTALL 모드를 활성화하고 , (?i)대소 문자를 구분하지 않는 모드를 활성화 \K하고, 지금까지 일치하는 텍스트를 생략하고 *?, 게으른 수량 자이며, (?=<Foobar>)이전 위치와 일치합니다 <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file( M여기서 파일 슬러 핑을 활성화합니다). 참고 pcregrep는 Mac OS grep사용자에게 좋은 솔루션입니다 .

데모를 참조하십시오 .

POSIX 기반이 아닌 엔진 :

  • - s수정 자 PCRE_DOTALL 수정 자 사용 : preg_match('~(.*)<Foobar>~s', $s, $m)( 데모 )
  • - 사용 RegexOptions.Singleline플래그 ( 데모 ) :
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    -var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - (?s)인라인 옵션 사용 :$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - s수정 자 (또는 (?s)시작시 인라인 버전) 사용 ( 데모 ) :/(.*)<FooBar>/s
  • - 플래그 re.DOTALL(또는 re.S) 또는 (?s)인라인 수정 자 ( demo )를 사용합니다 m = re.search(r"(.*)<FooBar>", s, flags=re.S)(그리고 if m:, print(m.group(1)))
  • - Pattern.DOTALL수정 자 (또는 인라인 (?s)플래그) 사용 ( demo ) :Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - (?s)패턴 내 수정 자 사용 ( demo ) :regex = /(?s)(.*)<FooBar>/
  • - (?s)수정 자 사용 ( demo ) :"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • -사용 [^]또는 해결 방법 [\d\D]/ [\w\W]/ [\s\S]( 데모 ) :s.match(/([\s\S]*)<FooBar>/)[1]
  • ( std::regex) 사용 [\s\S]또는 JS 해결 방법 ( 데모 ) :regex rex(R"(([\s\S]*)<FooBar>)");
  • -JavaScript에서와 동일한 방법을 사용하십시오 ([\s\S]*)<Foobar>. ( 참고 : 객체 의 MultiLine속성 RegExp은 때로는 .줄 바꿈 을 통해 일치 시킬 수있는 옵션으로 잘못 간주되는 반면, 실제로 는 JS 정규 표현식에서와 같이 문자열이 아닌 줄의 시작 / 끝과 일치하도록 행동 ^$행동 만 변경합니다 ) 행동.)

  • /m -MULTILINE 수정 자 사용 ( demo ) :s[/(.*)<Foobar>/m, 1]

  • -기본 R PCRE 정규 표현식-사용 (?s): regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]( 데모 )
  • ICU 정규식 엔진으로 구동되는 in stringr/ stringiregex 기능은 다음을 사용합니다 (?s). stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]( 데모 )
  • - (?s)시작할 때 인라인 수정자를 사용하십시오 ( demo ) :re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - dotMatchesLineSeparators또는 (?s)인라인 수정자를 패턴에 전달하십시오 .let rx = "(?s)(.*)<Foobar>"
  • -Swift와 동일하며 (?s)가장 쉽게 작동하지만 다음은 옵션 사용 방법입니다 .NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - (?s)수정 자 사용 ( demo ) : "(?s)(.*)<Foobar>"(Google Spreadsheets에서 =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

참고 사항(?s) :

POSIX가 아닌 대부분의 엔진에서 (?s)인라인 수정 자 (또는 임베디드 플래그 옵션)를 사용하여 .줄 바꿈을 일치 시킬 수 있습니다 .

패턴의 시작 부분에 배치되면 패턴 (?s)의 모든 바하 비어가 변경 .됩니다. 를 (?s)시작 후 어딘가에 배치 하면 패턴이 Python에 전달 되지 않는 한. 오른쪽에있는 것만 영향을받습니다 . Python에서는 위치에 관계없이 전체 패턴 이 영향을받습니다. 를 사용하여 효과를 중지 합니다. 수정 된 그룹은 지정된 범위의 정규 표현식 패턴에만 영향을 미치기 위해 사용될 수 있습니다 (예 : 개행 에서 첫 번째 일치를 만들고 두 번째 행은 나머지 행과 만 일치).rere(?s).(?s)(?-s)Delim1(?s:.*?)\nDelim2.*.*?.*

POSIX 참고 :

POSIX가 아닌 정규식 엔진에서는 모든 문자와 일치하도록 [\s\S]/ [\d\D]/ [\w\W]구문을 사용할 수 있습니다.

POSIX에서는 [\s\S]정규 표현식 이스케이프 시퀀스가 ​​대괄호 표현식 내에서 지원되지 않기 때문에 JavaScript 또는 POSIX 엔진이 아닌 다른 문자와 일치하지 않습니다. [\s\S]단일 문자와 일치하는 대괄호 표현식으로 구문 분석 \되거나s 또는 S.


5
프로필 페이지 또는 다른 항목 (+1)에서이 훌륭한 개요에 연결해야합니다.
Jan

1
이를 부스트 항목 에 추가 할 수 있습니다 . regex_constants 네임 스페이스에서 flag_type_ 's : perl = ECMAScript = JavaScript = JScript = :: boost :: regbase :: normal = 0이며 기본값은 Perl입니다. 프로그래머는이 #define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m를 반영하기 위해 해당 정규 표현식 플래그에 대한 기본 플래그 정의 를 설정 합니다. 그리고 중재자는 항상 인라인 수정 자입니다. (?-sm)(?s).*리셋되는 곳 .

1
bash를 추가 할 수 있습니까?
Pasupathi Rajamanickam

2
@PasupathiRajamanickam Bash는 POSIX 정규식 엔진을 사용합니다 .. 이 온라인 Bash 데모를 참조하십시오 .
Wiktor Stribiżew

1
당신은 흔든다 – 이것은 내가 본 것보다 복잡한 정규 표현식에 대한 가장 철저한 미니 튜토리얼이다. 당신은 당신의 대답이 받아 들여질 자격이 있습니다! Go답변 에 포함 시키는 것에 대한 찬사와 추가 투표 !
기네스 Llewelyn

68

Eclipse 검색을 사용하는 경우 "DOTALL"옵션을 사용하여 '.'을 만들 수 있습니다. 줄 구분자를 포함한 모든 문자와 일치 : 검색 문자열의 시작 부분에 "(? s)"를 추가하십시오. 예:

(?s).*<FooBar>

1
아니 어디서든 만에 정규 표현식의 맛은 어디 있지 루비에 확실히 인라인 수정을 지원하고, (?s)=>(?m)
Wiktor Stribiżew

bash에 대한 것이 있습니까?
Pasupathi Rajamanickam

38

많은 정규식 방언에서 /[\S\s]*<Foobar>/원하는대로 할 것입니다. 출처


2
"JavaScript와 VBScript에는 점이 줄 바꿈 문자를 일치시킬 수있는 옵션이 없습니다. 이러한 언어에서는 [\ s \ S]와 같은 문자 클래스를 사용하여 모든 문자를 일치시킬 수 있습니다." 대신. 대신 [\ s \ S] (공백 및 비 공백 일치)를 사용하십시오.
Allen

32

([\s\S]*)<FooBar>

점은 개행을 제외한 모든 문자와 일치합니다 (\ r \ n). 따라서 모든 문자와 일치하는 \ s \ S를 사용하십시오.


Objective-C를 사용하는 경우 문제를 해결합니다 [text rangeOfString:regEx options:NSRegularExpressionSearch]. 감사!
J. Costa

1
이것은 intelliJ의 찾기 및 바꾸기 정규식에서 작동합니다. 감사합니다.
barclay

작동합니다. 그러나 그것은 첫 번째 발생이어야합니다<FooBar>
Ozkan


13

우리는 또한 사용할 수 있습니다

(.*?\n)*?

탐욕없이 개행을 포함한 모든 것을 일치시키기 위해

이것은 새로운 줄을 선택적으로 만들 것입니다

(.*?|\n)*?

8

"."일반적으로 줄 바꿈과 일치하지 않습니다. 대부분의 정규식 엔진을 사용하면 S-flag ( DOTALL및 라고도 함 SINGLELINE)를 추가하여 줄 "."바꿈과 일치 시킬 수 있습니다. 실패하면 다음과 같이 할 수 [\S\s]있습니다.


8

Eclipse의 경우 다음 표현식을 사용했습니다.

jadajada 바 "

정규식 :

Foo[\S\s]{1,10}.*Bar*

5
/(.*)<FooBar>/s

s는 도트 (.)가 캐리지 리턴과 일치하게합니다.


잘못된 것 같습니다 (Chrome) : text.match (/ a / s) SyntaxError : RegExp 생성자 's'에 잘못된 플래그가 제공됨
Allen

JavaScript RegEx 엔진에서는 지원되지 않기 때문입니다. s플래그, PCRE 존재 (Perl과 PHP에서 사용할 수있는) 가장 완벽한 엔진. PCRE에는 10 개의 플래그가 있으며 JavaScript에는 3 개의 플래그 ( gmi) 만 있습니다.
Morgan Touverey Quilling

4

자바 기반 정규 표현식에서 사용할 수 있습니다 [\s\S]


1
백 슬래시가되어서는 안됩니까?
Paul Draper

그것들은 정규 표현식의 끝이 아닌 안으로 들어갑니다. 예 : / blah / s
RandomInsano

Java가 아닌 JavaScript를 의미한다고 생각하십니까? sJava에서 패턴에 플래그를 추가 할 수 있고 JavaScript에는 s플래그 가 없습니다 .
3limin4t0r

3

(.|\n)*(예를 들어)보다 효율적일 수 있습니다 [\s\S]*(언어의 정규 표현식에 같은 탈출을 지원하는 경우)와 수정 만드는을 지정하는 방법을 찾는 것보다. 또한 개행과 일치합니다. 또는 같은 POSIXy 대안을 사용할 수 있습니다 [[:space:][:^space:]]*.


3

RegexOptions.Singleline을 사용하면의 의미가 변경됩니다. 개행 포함

Regex.Replace (content, searchText, replaceText, RegexOptions.Singleline);



1

언어 내에서 사용되는 문맥에서 정규식은 줄이 아닌 문자열에 작용합니다. 따라서 입력 문자열에 여러 줄이 있다고 가정하면 정규식을 정상적으로 사용할 수 있어야합니다.

이 경우 "<FooBar>"가 있기 때문에 주어진 정규 표현식은 전체 문자열과 일치합니다. 정규식 구현의 사양에 따라 $ 1 값 ( "(. *)"에서 획득)은 "fghij"또는 "abcde \ nfghij"입니다. 다른 사람들이 말했듯이 일부 구현에서는 "."여부를 제어 할 수 있습니다. 개행과 일치하여 선택을 제공합니다.

라인 기반 정규 표현식 사용은 일반적으로 egrep와 같은 명령 행에 사용됩니다.


1

나는 같은 문제가 있었고 아마도 최선의 방법은 아니지만 작동합니다. 실제 경기를하기 전에 모든 줄 바꿈을 교체했습니다.

mystring= Regex.Replace(mystring, "\r\n", "")

이 경우 줄 바꿈이 실제로 중요하지 않도록 HTML을 조작하고 있습니다.

나는 위의 모든 제안을 운없이 시도했지만 .Net 3.5 FYI를 사용하고 있습니다.


.NET도 사용하고 있으며 (\s|\S)나를 위해 속임수를 쓰는 것 같습니다!
Vamshi Krishna

@VamshiKrishna .NET에서 모든 문자를 일치 (?s)시키는 데 사용 .하십시오. 사용하지 않으면 (\s|\S)성능이 저하됩니다.
Wiktor Stribiżew

1

Javascript에서는 [^] *를 사용하여 줄 바꿈을 포함하여 0에서 무한 문자를 검색 할 수 있습니다.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>


0

일반적으로 . 줄 바꿈과 일치하지 않으므로 시도하십시오.((.|\n)*)<foobar>


3
아뇨, 그렇게하지 마십시오. 줄 구분 기호를 포함하여 무엇이든 일치해야하는 경우 DOTALL (일명 / s 또는 SingleLine) 수정자를 사용하십시오. (. | \ n) 핵은 정규 표현식의 효율성을 떨어 뜨릴뿐만 아니라 정확하지도 않습니다. 최소한 \ r (캐리지 리턴) 및 \ n (줄 바꿈)과 일치해야합니다. 거의 사용되지는 않지만 다른 줄 구분 문자도 있습니다. 그러나 DOTALL 플래그를 사용하면 걱정할 필요가 없습니다.
Alan Moore

1
\ R은 Eclipse에서 줄 바꿈에 대한 플랫폼 독립적 인 일치입니다.
opyate

@opyate이 작은 보석은 매우 유용하기 때문에 이것을 답변으로 게시해야합니다.
jeckhart

대신 시도해보십시오. 그것은 내부 브래킷을 일치 선택 사양 고려하지 않을 것이다 \r:.((?:.|\r?\n)*)<foobar>
SSC-hrep3

0

Java의 특정 if 블록과 일치시키고 싶었습니다.

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

regExp를 사용하면

if \(isTrue(.|\n)*}

메소드 블록에 닫는 괄호가 포함되어 있으므로

if \(!isTrue([^}.]|\n)*}

와일드 카드 일치에서 닫는 중괄호를 제외합니다.


0

종종 우리는 하위 문자열 앞의 행에 몇 개의 키워드를 사용하여 하위 문자열을 수정해야합니다. xml 요소를 고려하십시오.

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

81을 다른 값 (40)으로 수정하려고한다고 가정합니다. 먼저을 식별 .UID.21..UID.한 다음 \n까지를 포함한 모든 문자를 건너 뜁니다 .PercentCompleted.. 정규식 패턴과 바꾸기 사양은 다음과 같습니다.

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

하위 그룹 (.|\n)이 누락 된 그룹 일 수 $3있습니다. 우리가하여 비 캡처 할 경우 (?:.|\n)다음은 $3입니다 (<PercentComplete>). 따라서 패턴은 다음과 replaceSpec같습니다.

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

교체는 이전과 같이 올바르게 작동합니다.


0

일반적으로 Powershell에서 3 개의 연속 라인을 검색하면 다음과 같습니다.

$file = get-content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # both

$file -match $pattern

# output
True

기괴하게도 이것은 프롬프트에서 유닉스 텍스트이지만 파일의 텍스트는 Windows입니다.

$pattern = 'lineone
linetwo
linethree
'

줄 끝을 인쇄하는 방법은 다음과 같습니다.

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# output
lineone\nlinetwo\nlinethree\n

-2

옵션 1

한 가지 방법은 s플래그 를 사용하는 것 입니다 (허용 된 답변과 동일).

/(.*)<FooBar>/s

데모 1

옵션 2

두 번째 방법은 m(멀티 라인) 플래그와 다음 패턴 중 하나 를 사용하는 것입니다 .

/([\s\S]*)<FooBar>/m

또는

/([\d\D]*)<FooBar>/m

또는

/([\w\W]*)<FooBar>/m

데모 2

정규식 회로

jex.im은 정규 표현식을 시각화합니다.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.