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


277

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

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


4
BTW에서이 문자는 "공백" [\r\f]입니다.
유진 야마 쉬

2
@eugeney 아직 양식 피드를 수행하는 사람이 있습니까? (\ f 's)
Aran Mulholland

1
@AranMulholland : 캐릭터 지향 프린터가있는 사람. 대부분의 프린터에는 문자 모드와 PostScript 또는 Hewlett Packard 인터페이스가 무엇이든 있으며 페이지를 넘기려면 양식 피드를 보내십시오.
Borodin

1
@Borodin Hewlett Packard는 PCL (Printer Control Language)이라고합니다.
CB_Ron

답변:


182

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


7
\h를 지원하는 언어에서만 작동합니다 PCRE.
Avinash Raj

14
@AvinashRaj :이 질문은 PCRE를 확실히 지원하는 Perl에 관한 것입니다
Borodin

2
@AvinashRaj : [[:blank:]]휴식 공간과 맞지 않는 것을 제외하고 –  또는"\xA0"
Borodin

6
\h1 개 이상의 연속적인 비 줄 바꿈 공백에서 메모장 ++에서 찾기 / 바꾸기를하고있는 사용 사례에 완벽하게 작동 한다고 언급하고 싶습니다. 다른 것 (간단한)은 효과가 없었습니다.
squidbe

8
Perl을 \h약간 비표준으로 만드는 것은의 포함입니다 MONGOLIAN VOWEL SEPARATOR. 유니 코드는 공백으로 간주하지 않습니다. 따라서 Perl \h은 POSIX blank( [[:blank:]]Perl, \p{Blank}Java) 및 Java 8과 다릅니다 \h. 틀림없이, 그것은 엣지 케이스입니다.
Aleksandr Dubinsky

362

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

/[^\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}+/) { ... }

4
영리하지만, 그 행동은 매우 놀랍습니다.
Qwertie

7
@ Qwertie : 놀라운 것은 무엇입니까? 무엇보다 덜 어색합니까?
ysth

9
매우 끔찍합니다.

9
이것은 매우 좋습니다. 요청에 따라 공백 문자 ( 일부 공백 문자가 아닌)와 일치 하고 줄 바꿈 문자를 제외합니다. 귀하의 솔루션은 "무엇이 공백 문자가 있는지"라는 질문과 관련이 없습니다. 이것이 바로 내가 찾던 것입니다. (@Rory가 지적한 것처럼 'newline'은 \r예를 들어 Windows 의 경우도 포함 할 수 있으므로 일치 항목에서 제외하는 것도 고려하십시오. /[^\S\r\n]/)
Timo

1
이것은 분명히 OP의 요구 와이 질문을 검색하는 거의 모든 사람들 (영어 사용자)을 충족시킬 것입니다. 그러나 여전히 나쁜 대답입니다. 사용 가능한 경우이 솔루션을 사용하는 데 대한 변명의 여지 \h가 없습니다.
Alan Moore

49

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

/[^\S\r\n]/

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


1
+1 Greg의 솔루션으로 인해 텍스트가 손상되어 잘 작동했습니다.
티모 후비 넨

줄 바꿈에 여전히 "\ r"을 사용하는 프로그램 수에 놀랄 수 있습니다. 내 문제가 파일이 이것을 사용했다는 것을 알아내는 데 때때로 시간이 걸렸습니다. 또는 MacRoman 문자 인코딩을 사용했습니다 ...
했거나

2
@Greg가 처음에 "잘못된"것으로 변경하여 크레딧을받지 않은 것 같습니다. 그렇기 때문에 여기에서 투표를합니다.
Andre Elrico

14

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

(?:(?!\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 )에서 작동합니다.

데모


이것이 최고의 솔루션입니다!
loretoparisi

13

당신이 찾고있는 것은 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]"

적절한 regexp 컴파일 플래그를 Java 컴파일에 추가하고 Java 7 이상을 실행해야합니다. 어쨌든 질문은 Java 또는 PCRE에 관한 것이 아니므로 이것은 중요하지 않습니다.
tchrist

@tchrist 이것을 지적 해 주셔서 감사합니다. 답변을 업데이트하겠습니다. 그러나 나는 대답이 무의미하다는 것에 동의하지 않습니다. 중요하지 않은 것은 perl원래 질문 의 태그입니다.
Aleksandr Dubinsky

1
@AleksandrDubinsky, \ p {Blank}는 JavaScript에서 지원되지 않으므로 "모든 정규식 표준에 대한 표준"이 아닙니다. -1
Valentin Vasilyev

가장 유익한 정보. 나는 일반적이고 완전한 "가로 공백"속기 문자 클래스가 존재하지 않으며 공포와 같은 공포 [\p{Blank}\u200b\u180e]가 필요 하다는 것을 아는 것이 혼란 스럽습니다 . 분명히 모음 구분 기호는 공백 문자로 간주 되지 않지만 왜 0 너비 공백이 \sand와 같은 클래스에 없는지 이해합니다 \p{Blank}.
Timo

후속 조치 : 나는 둘 다 '경계 중립적'으로 간주된다는 것을 읽었지만 그 이유 는 설명하지 않습니다 .
Timo

-4

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

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