[regex] 공백과 일치하지만 줄 바꿈과 일치하지 않습니다.

때로는 공백과 일치하지만 개행 문자는 일치시키지 않습니다.

지금까지 나는 의지했습니다 [ \t]. 덜 어색한 방법이 있습니까?



답변

Perl 버전 5.10 이상은 보조 수직 및 수평 문자 클래스 \v\h일반 공백 문자 클래스를 지원합니다.\s

가장 깨끗한 해결책은 가로 공백 문자 클래스 를 사용하는 것 \h입니다. 이것은 ASCII 세트의 탭과 공백, 확장 ASCII의 비 분리 공백 또는 이러한 유니 코드 문자와 일치합니다.

U+0009 CHARACTER TABULATION
U+0020 SPACE
U+00A0 NO-BREAK SPACE (not matched by \s)

U+1680 OGHAM SPACE MARK
U+2000 EN QUAD
U+2001 EM QUAD
U+2002 EN SPACE
U+2003 EM SPACE
U+2004 THREE-PER-EM SPACE
U+2005 FOUR-PER-EM SPACE
U+2006 SIX-PER-EM SPACE
U+2007 FIGURE SPACE
U+2008 PUNCTUATION SPACE
U+2009 THIN SPACE
U+200A HAIR SPACE
U+202F NARROW NO-BREAK SPACE
U+205F MEDIUM MATHEMATICAL SPACE
U+3000 IDEOGRAPHIC SPACE

수직 공간 패턴은 \v덜 유용하지만, 이러한 문자와 일치

U+000A LINE FEED
U+000B LINE TABULATION
U+000C FORM FEED
U+000D CARRIAGE RETURN
U+0085 NEXT LINE (not matched by \s)

U+2028 LINE SEPARATOR
U+2029 PARAGRAPH SEPARATOR

일치하는 7 개의 수직 공백 문자와 일치하는 \v18 개의 수평 문자가 있습니다 \h. \s스물 세 문자와 일치

모든 공백 문자는 겹치지 않고 세로 또는 가로 이지만 \hU + 00A0 NO-BREAK SPACE와 \v일치하고 U + 0085 NEXT LINE 과도 일치 하므로 적절한 하위 세트가 아닙니다.\s


답변

이중 음수를 사용하십시오.

/[^\S\r\n]/

즉, 공백이 아님 (자본 S가 보완 함) 또는 캐리지 리턴이 아니거나 줄 바꿈이 아닙니다. 외부를 배포하지 않음 (De Morgan의 법칙으로 , ^캐릭터 클래스 의 보완) 을 “공백이지만 캐리지 리턴 또는 줄 바꿈이 아님”과 같습니다. 패턴에 및 패턴을 모두 포함하면 모든 Unix (LF), 클래식 Mac OS (CR) 및 DOS-ish (CR LF) 줄 바꿈 규칙을 모두 올바르게 처리합니다 .\r\n

그것에 대해 내 말을 할 필요가 없습니다.

#! /usr/bin/env perl

use strict;
use warnings;

use 5.005;  # for qr//

my $ws_not_crlf = qr/[^\S\r\n]/;

for (' ', '\f', '\t', '\r', '\n') {
  my $qq = qq["$_"];
  printf "%-4s => %s\n", $qq,
    (eval $qq) =~ $ws_not_crlf ? "match" : "no match";
}

산출:

""=> 일치
"\ f"=> 일치
"\ t"=> 일치
"\ r"=> 일치하지 않습니다
"\ n"=> 일치하지 않습니다

세로 탭은 제외하지만 v5.18에서 해결되었습니다. .

너무 거칠게 반대하기 전에 Perl 문서는 동일한 기술을 사용합니다. perlrecharclass“공백”섹션에있는 각주 읽기

Perl v5.18 이전 \s에는 세로 탭과 일치하지 않았습니다. [^\S\cK](모호하게) \s전통적으로 한 것과 일치합니다 .

perlrecharclass동일한 섹션 에서도 언어 교사의 이중 부정에 대한 반대를 불쾌하게하지 않는 다른 접근법을 제안합니다.

로케일 및 유니 코드 규칙 외부 또는 /a스위치가 적용되는 경우 ” Perl v5.18부터 세로 탭 ” \s과 일치 [\t\n\f\r ]하고 일치 \cK합니다. ” 폐기 \r하고 \n떠날 /[\t\f\cK ]/일치 공백하지만 줄 바꿈하지 않는.

텍스트가 유니 코드 인 경우 아래에 설명 된 설명서 섹션 의 표에서 패턴을 구성하려면 아래 하위와 유사한 코드를 사용 하십시오 .

sub ws_not_nl {
  local($_) = <<'EOTable';
0x0009        CHARACTER TABULATION   h s
0x000a              LINE FEED (LF)    vs
0x000b             LINE TABULATION    vs  [1]
0x000c              FORM FEED (FF)    vs
0x000d        CARRIAGE RETURN (CR)    vs
0x0020                       SPACE   h s
0x0085             NEXT LINE (NEL)    vs  [2]
0x00a0              NO-BREAK SPACE   h s  [2]
0x1680            OGHAM SPACE MARK   h s
0x2000                     EN QUAD   h s
0x2001                     EM QUAD   h s
0x2002                    EN SPACE   h s
0x2003                    EM SPACE   h s
0x2004          THREE-PER-EM SPACE   h s
0x2005           FOUR-PER-EM SPACE   h s
0x2006            SIX-PER-EM SPACE   h s
0x2007                FIGURE SPACE   h s
0x2008           PUNCTUATION SPACE   h s
0x2009                  THIN SPACE   h s
0x200a                  HAIR SPACE   h s
0x2028              LINE SEPARATOR    vs
0x2029         PARAGRAPH SEPARATOR    vs
0x202f       NARROW NO-BREAK SPACE   h s
0x205f   MEDIUM MATHEMATICAL SPACE   h s
0x3000           IDEOGRAPHIC SPACE   h s
EOTable

  my $class;
  while (/^0x([0-9a-f]{4})\s+([A-Z\s]+)/mg) {
    my($hex,$name) = ($1,$2);
    next if $name =~ /\b(?:CR|NL|NEL|SEPARATOR)\b/;
    $class .= "\\N{U+$hex}";
  }

  qr/[$class]/u;
}

다른 응용

이중 음수 트릭은 알파벳 문자를 일치시키는데도 유용합니다. 그 기억 \w일치 “단어 문자,”알파벳 문자 숫자와 밑줄을. 우리는 추악한 미국인들이 때때로 이렇게 말합니다.

if (/[A-Za-z]+/) { ... }

그러나 이중 음수 문자 클래스는 로케일을 존중할 수 있습니다.

if (/[^\W\d_]+/) { ... }

이런 방식으로“단어 나 밑줄이 아닌 단어 문자”를 표현하는 것은 약간 불투명합니다. POSIX 문자 클래스는 의도를보다 직접적으로 전달합니다

if (/[[:alpha:]]+/) { ... }

또는 szbalint가 제안한 유니 코드 속성

if (/\p{Letter}+/) { ... }


답변

캐리지 리턴을 포함 하는 Greg의 답변 변형 :

/[^\S\r\n]/

이 정규식은 /[^\S\n]/no 보다 안전 \r합니다. 내 추론은 Windows가 줄 \r\n바꿈에 사용하고 Mac OS 9는 사용했습니다 \r. 요즘 \r없이는 찾을 수 없지만 찾을 \n경우 개행을 의미 할 수는 없습니다. 따라서 \r개행을 의미 할 수 있기 때문에 개행도 제외해야합니다.


답변

아래 정규식은 공백과 일치하지만 줄 바꿈 문자는 일치하지 않습니다.

(?:(?!\n)\s)

데모

당신은 또한 캐리지 리턴을 추가 할 경우 추가 \r|부정적인를 내다 내부 연산자.

(?:(?![\n\r])\s)

데모

+캡처하지 않은 그룹 뒤에 추가 하여 하나 이상의 공백을 일치시킵니다.

(?:(?![\n\r])\s)+

데모

사람들이 왜 [[:blank:]]수평 공백 ( 공백 및 탭)과 일치 하는 POSIX 문자 클래스를 언급하지 못한 지 모르겠습니다. ) . 이 POSIX chracter 클래스는 BRE ( Basic REgular Expressions ), ERE ( Extended Regular Expression ), PCRE ( Perl Compatible Regular Expression )에서 작동합니다.

데모


답변

당신이 찾고있는 것은 POSIX blank문자 클래스입니다. Perl에서는 다음과 같이 참조됩니다.

[[:blank:]]

자바에서 (활성화하는 것을 잊지 마십시오 UNICODE_CHARACTER_CLASS) :

\p{Blank}

유사한 \hPOSIX blank는 몇 가지 정규식 엔진 ( 참조 )에서 지원됩니다 . 주요 이점은 그 정의가 부록 C : 유니 코드 정규 표현식의 호환성 속성에 고정되어 있다는 것입니다 를 지원하는 모든 에서 표준 있다는 것입니다. (예를 들어, Perl에서는 \h을 추가로 선택합니다 MONGOLIAN VOWEL SEPARATOR.)\h POSIX 문자 클래스는 종종 기본적으로 ASCII 인 반면, 엔진은 어느 엔진에 동의하지 않더라도 항상 유니 코드 문자를 감지합니다. -전용 (Java와 동일).

그러나 문제는 유니 코드를 고수하더라도 100 % 문제를 해결하지 못한다는 것입니다. 유니 코드에서 공백으로 간주되지 않는 다음 문자를 고려하십시오.

앞서 언급 한 몽골어 모음 분리기는 좋은 이유가 포함되어 있지 않습니다. 200C 및 200D와 함께 단어 (AFAIK)에서 발생하므로 다른 모든 공백이 준수하는 기본 규칙을 위반합니다. 토큰으로 토큰 화 할 수 있습니다. 그것들은 더 많은 수정 자와 같습니다. 그러나 ZERO WIDTH SPACE, WORD JOINERZERO WIDTH NON-BREAKING SPACE (가 바이트 순서 표시 이외로 사용 된 경우) 내 책에 공백 규칙에 맞게. 따라서 수평 공백 문자 클래스에 포함시킵니다.

자바에서 :

static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"


답변

m/ /g에 공간을 주면 / /작동합니다. 또는 사용 \S— 탭, 줄 바꿈, 공백 등의 모든 특수 문자를 대체합니다.


답변