어디서 배울 지 묻지 않습니다 . 온라인에서 좋은 자료와 책 등을 많이 찾았습니다.
그러나 어떻게 도대체 내가 그들을 해결합니다. 그것의 시작은 어디입니까? 정규식 프로세서는 언제 텍스트를 진행합니까, 언제 서서 다른 일치를 시도합니까? 기타
이집트 피라미드에서 상형 문자를 찾으려고합니다.
어디서 배울 지 묻지 않습니다 . 온라인에서 좋은 자료와 책 등을 많이 찾았습니다.
그러나 어떻게 도대체 내가 그들을 해결합니다. 그것의 시작은 어디입니까? 정규식 프로세서는 언제 텍스트를 진행합니까, 언제 서서 다른 일치를 시도합니까? 기타
이집트 피라미드에서 상형 문자를 찾으려고합니다.
답변:
저는 Automata 이론에 대한 지식이 이해에 중요 하다고 생각합니다 .
오토 마톤이 무엇인지, 정규 언어 가 어떻게 정의 되는지 이해하면 정규 표현식 을 이해하는 것이 훨씬 쉬울 것입니다.
다양한 구현 사이의 특정 구문과 차이점에 관해서는 ... 기억해야 할 것이 있습니다. 있습니다 보조 그것에 대해 너무.
편집하다
아래의 의견 중 일부는 중요한 사항을 제기했습니다.
정규 표현식 (대부분의 프로그래밍 언어로 구현 됨)은 오토마타 이론에서 정규 표현식의 상위 집합이라는 것을 잊지 마십시오. 좋은 이론적 배경은 시작하기에 유용한 곳이지만 모든 것을 알려주지는 않습니다. (감사합니다, David Thornley)
여러 의견 제시 자들은 이론적 기초를 배우지 않고도 다양한 정규식 구문을 배울 수 있다고 말합니다. 작동 방식을 완전히 이해하지 않고 구문을 배울 수 있다는 것은 사실이지만, OP에 대한 이해는 완전히 이해하는 것이 었습니다. 문제는 실제 기반에 관한 것이 었습니다. 프로세서는 언제 발전합니까? 언제 멈추나요? 어떻게 일치하는지 결정합니까? 이것이 기초이며, 이론이며, 오토마타 이론에 기초합니다. 물론, 엔진 작동 방식을 몰라도 자동차를 운전할 수 있습니다. 그러나 "가스가 실제로 어떻게 구동되는지"라는 질문을 받으면 엔진이 어떻게 만들어 졌는지 에 대해 이야기해야합니다.
연습함으로써.
웹 스크래핑으로 재미있게 배웠습니다. 나는 그저 재미로 혼자서 그런 것이 아니라고 확신합니다.
예 : 좋아하는 스포츠 웹 사이트에서 최신 축구, 테니스 (실제로 좋아하는 스포츠) 점수를 검색하는 코드를 작성하십시오. 코드를 작성하여 페이지를로드하고 정규 표현식으로 점수를 추출하여 콘솔이나 텍스트 파일로 출력하십시오. 정규식을 사용하면 점수 만 검색하고 다른 항목은 검색하지 않아야합니다. 때때로 이것은 꽤 도전적 일 수 있습니다 :-)
두 번째 예 : 좋아하는 웹 코믹의 사진을 검색하는 코드 (예 : Sinfest 를 많이 좋아함 )를 하드 드라이브 어딘가에 저장하는 코드를 작성하십시오. "img"태그와 그 내용을 검색하려면 정규식 만 사용하십시오. 선택적으로 제목이 어딘가에 저장된 경우 제목을 검색하십시오.
나는 당신이 리소스를 요구하지는 않지만 Jeffrey EF Friedl의 정규 표현식 마스터 링 은 그들이 어떻게 작동하고 어떻게 사용하는지 배웠습니다. 다른 것들을 파싱하기 위해 많은 것들을 사용하는 시점에 도달 한 후에도 첫 번째 장에는 나에게 새로운 것들이있었습니다.
그 정규 표현식을 이해하고 싶습니까? 이 책을 읽으십시오.
그것의 시작은 어디입니까? 정규식 프로세서는 언제 텍스트를 진행합니까, 언제 서서 다른 일치를 시도합니까? 기타
먼저 목표 를 명확히 하고 학습 스타일 을 알아내는 것부터 시작하겠습니다 .
귀하의 질문에 대해 가장 큰 충격은 "정규 표현을 어떻게 배우나요?"라는 질문입니다. "정규식 엔진은 어떻게 내부적으로 작동합니까?" 그 두 가지가 서로 관련이 있다는 것을 암시하는 것 같습니다. 어쩌면 당신은 무언가를 분해하거나 직접 만들어서 어떻게 작동하는지 배우는 사람 일 것입니다.
초보자 응용 프로그램의 경우 일반적으로 도구를 효과적으로 사용하기 위해 도구의 작동 방식을 이해할 필요가 없습니다. 목재에 구멍을 뚫기 위해 드릴 모터가 어떻게 작동하는지 알 필요는 없습니다. 당신이하는 방법을 이해하는 데 필요한 사용하는 드릴을, 어떻게하지하는 구축 드릴.
그래서 당신의 목표는 무엇입니까? 정규식 엔진 을 작성하는 방법을 배우려고 합니까? 또는 정규식 을 효과적으로 사용하여 비즈니스 문제를 해결 하는 방법을 배우고 싶습니까? 이러한 다른 목표를 달성하려면 다른 학습 기술이 필요할 수 있습니다.
정규식 엔진의 작동 방식에 대한 특정 질문을 해결하려면 다음이 필요합니다. 정규 표현식에 대한 "고전적인"이론적 접근 방식은 정규 표현식을 비 결정적 유한 오토 마톤에 대한 청사진으로 사용한 다음 동등한 결정 론적 유한 오토 마톤을 빌드 한 다음 입력에 대해 해당 오토 마톤을 실행하는 것입니다.
실제로 여러 가지 이유로 아무도 실제로 이것을하지 않습니다 . 첫째, 가능한 수의 입력 문자 수를 곱한 상태 수에는 작은 정규식이라도 엄청나게 큰 상태 전이 테이블이 생성됩니다. 물론 대부분은 압축 할 수 있지만 여전히 많은 전환 규칙입니다. 둘째, 다른 접근 방식은 일반적으로 더 빠릅니다. 셋째, 소위 "정규"표현식은 현대 정규 표현식 라이브러리에 있으며 아무 것도 아닙니다. 그것들은 전혀 정규 언어 가 아닙니다 . 그것들은 종종 유한 오토마타 언어가 아닌 푸시 다운 오토마타로 인식됩니다.
(나는이 모든 것들이 어떻게 작동하는지에 대한 긴 시리즈를 작성하기 시작했지만 첫 12 기사 만 읽었을 때 증기가 부족했습니다 . 기본 정규 표현식의 이론적 배경에 대한 간단한 입문서를 원한다면 흥미로울 것입니다.)
실제 정규 표현식 엔진은 일반적으로 역 추적 전략을 사용합니다. 10 년 전에 JScript 엔진 용으로 구축 한 정규식 엔진은 이제 정규식을 시퀀스 인식 및 이전 상태로의 역 추적을위한 기본 요소를 포함하는 바이트 코드 언어로 컴파일합니다. 그런 다음 해당 바이트 코드 언어에 대한 인터프리터를 작성했습니다.
정규 표현식 을 사용 하는 방법을 상당히 확실하게 이해하기 전에 정규 표현식 엔진의 작동 방식을 이해하려고하지 않습니다 . 다양한 엔진에 대한 최적화 전략을 파기 시작하기 전에 집중하십시오.
"[0-9]{3}"
있는 세 자리 번호와 일치 할 수 있으며, 세 자리 숫자 480은 일반에 대한 예입니다 일치하는 표현.
도대체 어떻게해야합니까?
새로운 것처럼 :
10 Study
20 Practice
30 goto 10
대부분의 성공적인 교사는 먼저 과목에 약간의 배경 지식을 제공함으로써 어떤 과목을 가르치기 시작합니다. 배우고있는 내용과 배우는 이유 를 이해하는 것이 중요 합니다.
정규 표현식은 텍스트에서 패턴을 일치시키는 수단입니다. 그것은 다른 많은 프로그래밍 언어에 통합 된 선언적 언어입니다.
나는 정규 표현식을 표현하는 데 유용는 선언적 언어의 것을 강조하고 싶습니다 무엇 에 맞게 문자열,하지만 그들은 어떤 식 으로든 표현으로하지 않는 방법 프로그램이 일치하는 것에 대해 이동하는 것입니다. 이러한 이유로 다른 RegEx 파서를 사용하여 동일한 프로그래밍 언어에서 정규식을 매우 빠르고 매우 느리게 사용할 수 있습니다.
정규 표현식을 작성하는 이유는 대부분의 프로그래밍 언어를 작성하는 경우와 같습니다. 프로그래머는 동일한 복잡한 작업을 반복해서 수행하고 더 간단한 코드 작성 방법을 원한다고 결정했습니다.
어떤 사람들은 나의 이전 문장에 대해 다음과 같은 내용으로 무언가를 말함으로써 불평 할 것입니다.
사실이야
RegEx 는 프로그램을 더 단순 하게 만들지 않으며 RegEx는 프로그램을 간단 하게 작성 합니다. 모든 올바른 사례가 올바르게 일치하고 모든 잘못된 경우가 일치하지 않도록 테스트를 철저히 수행해야합니다. "모두"를 테스트하는 것은 정말 어렵고 복잡한 패턴으로 "가장 많이"를 테스트하는 것은 정말 어렵습니다. 최악의 경우, 여전히 "일부"사례를 테스트해야합니다.
브라우저에서 쉽게 테스트 할 수 있고 RegEx 리터럴을 사용하는 동안 문자열 이스케이프를 수행 할 필요가 없기 때문에 JavaScript의 RegEx 엔진을 엄격하게 선택한 몇 가지 예를 통합 할 수 있습니다.
일반 문자열 일치를 수행하면 한 문자열 값을 다른 문자열 값과 비교하여 테스트합니다. 그것들은 어느 곳에서나 올 수 있지만 결국 두 문자열을 서로 비교해야합니다.
if ( 'foo' == 'bar' ) doSomething();
이 예제 는 아무것도 하지 않기 때문에 짜증납니다 .
if ( foo == 'bar' ) doSomething();
훨씬 낫다; 지금, 우리는 실제로 어떤 일이 이루어질 것인지 미리 알지 못합니다. 이제 사용자 입력을 받아 들일 수 있습니다.
if ( prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();
훌륭하고, 이제는 사용자가 입력 할 수 있으며 bar
, "bar"
작동하지 않거나 "BAR"이 작동하지 않거나 BRA
100 번 입력했지만 아무 일도 일어나지 않는다고 사용자로부터 버그 보고서를받을 때까지 어떤 일 이 발생합니다.
맞춤법 오류와 추가 문자를 무시 'bar' != 'BAR'
하고 프로그래머는 문자가 잘못된 경우를 테스트하는 방법을 고려해야합니다.
간단한 해결책을 사용하십시오 toLowerCase
. 훌륭하게 작동하지만 일치 할 때 미국 영어보다 영국 영어를 사용하는 사용자는 something == 'color'
어떻습니까? 이제 일치해야합니다 something == 'color' || somthing == 'colour'
.
짧고 간단한 패턴은 긴 반복 코드로 매우 빠르게 변환됩니다.
색상 예는 다음과 간단히 일치 할 수 있습니다.
/colou?r/.test( something )
정규 표현식의 기본 사항을 제대로 이해하면 휠을 재발 명하는 데 걸리는 시간을 크게 줄일 수 있습니다.
정규식을 구현하는 대부분의 언어에는 해당 언어 내에서 정규식을 사용하는 특정 구문에 사용할 수있는 리소스가 하나 이상 있습니다. 에 대한 하나의 자바 스크립트는 MDN에서 찾을 수 있습니다
읽어.
그것의 모든.
그런 다음 다시 읽으십시오.
학습하는 데 시간이 걸리고 투자로 생각하십시오. RegEx를 배우는 데 1 시간이 걸리면 다음에 문자열 패턴 일치를 수행해야 할 때 1 시간이 절약되고 그 다음에 다음 시간에는 1 시간이 절약됩니다.
RegEx에 대한 모든 내용을 읽은 후에는 대부분 이해하지 못할 것입니다. 당신이 실제로하지 않을 때문이다 하고 그것으로 아무것도.
이 예제에서 JS를 선택한 이유를 언급했지만 브라우저에서 엉망으로 만들 것을 권장합니다. 빠르고, URL 표시 줄에서 바로 할 수 있습니다.
JS에는 RegEx를 사용하는 몇 가지 다른 간단한 방법이 있습니다.
string.match( regex )
regex.exec( string )
regex.test( string )
다음과 같은 간단한 것으로 시작하십시오.
javascript:'color'.match(/colou?r/);
문에 발을 넣는 쉬운 방법입니다. 그것을 가지고 놀고, 어떤 것이 일치하는지, 그렇지 않은 것을 보아라.
실습에 빠져 있으면 계속하십시오 30
. 자세한 내용을 읽으려면 읽어야하지만 배운 내용을 실제로 이해하려면 연습해야합니다.
Brian Kernighan은 Beautiful Code 책에 간단한 정규식 프로세서를 작성합니다 . 나는 당신이 리소스를 찾고 있지 않다는 것을 알고 있지만 내부에서 기본 구현 을 보는 것이 도움이 될 수 있습니다.
정상적인 개발에서 디버깅 코드는 매우 유용한 통찰력을 제공 할 수 있습니다. 정규 표현식은 다르지 않습니다. 따라서 광고처럼 들릴 위험이 있으므로 RegexBuddy를 얻으 십시오 . 표현식과 입력 문자열을 처리 할 때 엔진이 수행하는 작업을 시각적으로 표시하는 훌륭한 도구가 있습니다.
정규 표현식은 매우 빠르게 복잡해질 수 있으므로 자습서를 사용하여 학습을 시작하는 것이 좋습니다. 가장 간단한 정규식 형식은 검색하려는 내용을 나타내는 문자열입니다. 불행히도, 특수 검색 규칙을 정의하려면 특정 문자가 필요하며 이러한 문자를 이스케이프하거나 유효하지 않거나 잘못된 정규식을 작성해야합니다.
내 충고는 당신이 찾고있는 것의 예에서 시작하여 그것을 피하는 것입니다. 다시 말해, 괄호 안에있는 것을 찾고 있다면 검색중인 텍스트에서 그러한 문자열 중 하나를 예로 들어 보겠습니다. (this is an example of something you'd want to find)
리터럴 문자를 검색 할 수 있도록 문자를 이스케이프하여 시작하십시오.
\(this is an example of something you'd want to find\)
테스트하고 예제를 올바르게 찾는 지 확인하십시오. 그런 다음 표현식을 일반화하여 찾은 예제뿐만 아니라 그러한 텍스트를 찾으십시오. 따라서 다음과 같이됩니다.
\([^)]*\)
(0을 포함하여 여러 번 발생하는 경우 ""가 아닌 문자를 의미합니다).
다시 테스트하고 예제뿐만 아니라 다른 사람들도 좋아하는지 확인하십시오. 인터넷에서보다 복잡하지만 빈번한 정규 표현식을 검색하고 기존 정규 표현식으로 패치하여 모든 가능성에 대해 걱정할 필요가 없습니다.
그게 다야. 그리고 오, 배우고 사랑합니다 \ Q ... \ E. 대부분의 정규 표현식 언어에서 \ Q는 리터럴 패턴의 시작을 나타내고 \ E는 특히 정교한 패턴 검색을 처리해야하고 패턴을 이스케이프 처리하는 방법을 모르는 경우를 나타냅니다. 그것은 두 번 이상 내 목숨을 구했습니다.
간단한 질문에 대한 간단한 답변을 드리겠습니다. 먼저 정규식 (RegEx)이 무엇인지, 무엇을하고 무엇을 사용하는지 이해해야합니다. 그런 다음 시작하기에 좋은 도구입니다.
무엇입니까? RegEx는 패턴 일치를 표현하는 언어입니다. 즉,이를 사용하면 텍스트에서 패턴을 인식하거나 찾는 문자 조합을 만들 수 있습니다. 이것이 어떻게 유용합니까? 프로그래밍에서 컴퓨터에 일부 소스 (사용자 입력, 웹 페이지 등)의 텍스트를 일치 시키도록하고 특정 텍스트 패턴이 포함되어 있는지 여부를 감지 할 수 있습니다. 예를 들어, 마침표 (.)는 문자 또는 숫자를 나타냅니다. 중괄호 안의 숫자는 반복 횟수를 나타내므로 ". {1,30}"은 1 ~ 30 회 반복되는 모든 문자를 나타냅니다. 즉, 빈 문자열을 가질 수 없으며 30보다 길 수 없습니다 문자. 그리고 거기서부터 계속됩니다.
학습을 시작하는 방법? 내가 본 최고의 도구는 Expresso 이지만 Windows 전용입니다. 표현식에 추가하려는 요소를 클릭하는 매우 광범위한 GUI가 있으며, 테스터는 다양한 입력과 비교하여 결과를 확인합니다. 나는 Mac에서 좋은 것을 보지 못했지만 (VMWare에서 Windows를 실행하고 있으므로 실제로 Mac 버전이 필요하지 않음) Linux를 찾는 데 많은 시간을 소비하지 않았습니다.
좋은 참고 자료 외에도 실제로 배우는 방법 은 훌륭한 학습 도구를 사용하는 것입니다. 하나는 오픈 소스 Vim 편집기를 사용하고 있으며 두 가지 옵션이 설정되어 있습니다.
다른 하나는 무료 도구 호출 RegExCoach 를 사용하는 것 입니다. 검색하려는 텍스트를 붙여 넣은 다음 다른 창에서 정규식을 개발합니다. Vim과 마찬가지로 성공적인 경기를 강조합니다.
기본 문자열 비교로 시작합니다. 매우 쉽지만 강력하지는 않습니다.
다음으로, "greek"와 "GreeK"가 같은지 비교하기 위해 대소 문자를 구분하지 않는 비교가 필요합니다. 이것은 조금 더 강력합니다.
언젠가 철자에 약간의 차이가있어 두 단어가 동등하게 비교되는 것을 막지 않아야합니다. 즉 "organize"와 "organize"는 동등하게 비교해야합니다. 당신은 앉아서 이것을하는 코드를 작성하고 행복합니다.
조금 더 추상화하고 "ize"로 끝나는 모든 단어가 영국 철자법에서 형제들과 동등하게 비교되기를 원할 때까지. 또는 일부 문자열을 특정 횟수만큼 반복합니다. 그리고 물론, 당신은 모든 것을 결합해야합니다.
등등. 마지막으로 모든 문자가 자신을 나타내는 것은 아닙니다. 다른 것은 정규 표현식이 아닙니다. 문자열 집합에 대한 설명으로 볼 수 있습니다.
그런 다음 상당히 쉽고 다음과 같은 3 가지 기본 원칙을 따릅니다.
기본 정규 표현식이 있습니다. 자체를 나타내는 문자, 문자 클래스, 대문자의 경우 \ d 또는 \ p {Lu}와 같은 문자 클래스의 경우 편리하지 않은 약어입니다.
r1과 r2가 정규 표현식이면 r1r2 r1 | r2 (r1)도 있습니다.
마지막으로 반복 수정 자 : r? r * r + r {n, m}
이것이 가장 알아야 할 사항입니다. 필요할 때 조회 할 수있는 모든 것
두 가지 좋은 답변은 정규 표현식의 이론을 배우고 실천하는 것입니다. 또한 진지한 경우 도움이되는 훌륭한 시각적 정규식 도구를 사용하는 것이 좋습니다.
예를 들어 RegexBuddy 에는 정규 디버그 실행을 단계별로 안내하는 시각적 디버그 모드가 있으며 각 단계에서 정규식 엔진이 수행하는 작업을 강조 표시 및 설명 텍스트를 통해 표시합니다. 있어 이 디버깅 시연 동영상 사이트에가.
우리가 줄 수있는 모든 것은 배울 수있는 더 많은 자료입니다. 이 질문 자체는 리소스입니다.
그건 그렇고, 나는이 사이트에서 정규 표현식을 매우 쉽게 배웠습니다 : http://www.regular-expressions.info/
저는 어휘 분석기와 파서를 구축하는 데 사용되는 flex와 bison을 배워 정규 표현을 배웠습니다. 정규 표현식이 없으면 파서를 가질 수 없었고, 책 lexx와 yacc 는 너무 빨리 움직이지 않고 이론을 걷는 데 엄청나게 좋습니다.
기본적으로 오늘날 모든 정규식 엔진은 동일한 원칙을 따릅니다. 그것들은 모두 유한 한 상태 머신 이며, 만약 당신이 정말로 그것을 이해했다면, 당신은 당신이 작성하는 거의 모든 코드를 사용할 수 있습니다. 그것은 재귀를 배우는 것과 비슷합니다. 일단 그것을 얻으면, 본능적으로 문제에 적용합니다. 올바른 도구로 쉽게 해결할 수 있지만 도구 없이는 매우 어렵습니다.
정규 표현식과 비교하여 lexx와 yacc를 배우는 또 다른 점은 내부적으로 어떻게 작동 하는지 배우는 것 입니다. 프로그램의 미래 전망, 경기 종료 이유, 데이터 보유 방법 등. 포인터를 이해하는 것은 절대적으로 필요한 일이지만, lexx와 yacc를 받고 처음부터 살펴보면 요청한 모든 내용을 배우고 나머지 경력을위한 강력한 도구를 갖게됩니다.
이 질문 에는 학습을위한 많은 자료와 제가 함께 던진 플렉스 스켈레톤이 포함됩니다.
더 이상, 먼저 문제를 해결하고 문자열을 "토큰 화"하는 쉬운 방법이 없는지 확인하려고합니다.
하나를 찾을 수 없으면 문자열에서 원하는 것을 일치시키지 않는 문제로 간주합니다. 대신 원하지 않는 것과 일치하지 않는 문제입니다. 이것은 대부분 정규 표현식이 욕심 많기 때문입니다. 그러나 그것은 내가 원하는 것을 얻는 접근 방식으로 나에게 도움이되었습니다.
예를 들면 다음과 같습니다.
string = "Sep 22 19:57:38 host fcron[9137]: \
Job fbsetbg -r $HOME/backgrounds/ \
started for user user (pid 9138)"
분과 일치 시키려면 :
string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/ # correct and good
다른 모든 것들과 함께 시간을 찾으려고 노력하는 대신 뚜렷한 경계를 찾으십시오.
예제는 약간 고안되었지만, 내가 생각해 낼 수있는 모든 것입니다.
내가 사용한 한 가지 접근 방식은 구문 업데이트가 필요한 오픈 소스 프로젝트를 찾은 다음 점점 더 복잡한 sed 스크립트를 작성하는 것이 었습니다.이 스크립트는 많은 정규식으로 구성되었습니다.
스크립트는 각 오픈 소스 프로젝트에서 다양한 파일에 대해 실행해야했습니다. 그런 다음 스타일이 다른 여러 프로젝트에 대해 실행하십시오. 나는 매우 간단한 것으로 시작하여 %s/before/after
너무 많은 경우와 일치한다는 것을 알았습니다. 이를 막기 위해 더 많은 것을 추가했습니다. 그런 다음 다른 변경이 필요한 다른 구문 스타일을 사용하여 다른 프로젝트를 찾았습니다.
결국 나는 결국
이 접근 방식에서 도움이 필요했습니다
루비, 자바 스크립트 등 다양한 언어를위한 사이트가 많이 있으며,이를 통해 표현과 샘플 텍스트로 즉시 만족할 수 있습니다. 이것들은:
한 사이트에서 여러 언어로 정규 표현식
경기 그룹에 초점 :
나는 곱셈 테이블을 배우는 것과 비슷한 정규 표현식을 배우는 것을 발견했습니다. 그렇습니다. 그 뒤에있는 아이디어를 이해해야하지만 궁극적으로 자주 반복해야합니다.
배우면서 나는 하루에 몇 번 정규식 운동을한다는 목표를 세웠습니다. 실제로, 이것은 하루에 한 번 이상을 의미했습니다. 화면에서 문자열이나 텍스트를 보려고 시도하고 "여기에서 모든 이메일 주소를 가져올 수 있습니까?" '코드'라는 단어는 명사 대신 동사로 사용됩니다. "
몇 주 동안 그렇게하면 실제로 보상을 받았으며 물론 정기적 인 검토와 새로 고침이 필요합니다. 나는 하나에 대한 예정입니다.
실시간으로 정규식을 테스트 할 수 있기 때문에이 온라인 도구도 유용하다는 것을 알았습니다. http://www.gethifi.com/tools/regex