Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby 정규 표현식 마스터하기

Ruby 정규식(ruby regex 줄여서) 추가 처리를 위해 데이터를 추출할 목적으로 문자열 내부의 특정 패턴을 찾는 데 도움이 됩니다.

정규 표현식의 두 가지 일반적인 사용 사례에는 유효성 검사 및 구문 분석이 있습니다.

예를 들어 :

ruby regex가 있는 이메일 주소를 생각해 보세요. 유효한 이메일 주소의 모양을 정의할 수 있습니다. 즉, 귀하의 프로그램은 유효한 이메일 주소와 유효하지 않은 이메일 주소를 구별할 수 있습니다.

Ruby 정규 표현식 마스터하기

루비 정규식은 두 개의 슬래시 사이에 정의됩니다. 다른 언어 구문과 구별하기 위해. 가장 단순한 표현은 단어 또는 한 글자와도 일치합니다.

예를 들어 :

# Find the word 'like'
"Do you like cats?" =~ /like/

이것은 단어가 발견된 경우(성공한 일치) 또는 nil인 경우 단어가 처음 나타나는 인덱스를 반환합니다. 그렇지 않으면. 인덱스에 신경 쓰지 않는다면 String#include? 방법.

문자열이 정규식과 일치하는지 확인하는 또 다른 방법은 match를 사용하는 것입니다. 방법:

if "Do you like cats?".match(/like/)
  puts "Match found!"
end

지금:

날짜, 전화번호, 이메일, URL 등과 같은 항목을 일치, 캡처 및 대체할 수 있도록 보다 고급 패턴을 구축하는 방법을 배우게 됩니다.

캐릭터 클래스

문자 클래스를 사용하면 일치시킬 문자 범위 또는 목록을 정의할 수 있습니다. 예:[aeiou] 모든 모음과 일치합니다.

:문자열이 포함합니까? 모음?

def contains_vowel(str)
  str =~ /[aeiou]/
end

contains_vowel("test") # returns 1
contains_vowel("sky")  # returns nil

금액은 고려되지 않습니다. 그 방법을 곧 알게 될 것입니다.

범위

범위를 사용하여 모두 입력하지 않고도 여러 문자나 숫자를 일치시킬 수 있습니다. 즉, [2-5]와 같은 범위 [2345]와 동일합니다. .

몇 가지 유용한 범위:

  • [0-9] 0에서 9까지의 숫자와 일치
  • [a-z] a에서 z까지의 모든 문자와 일치(대문자 없음)
  • [^a-z] 부정 범위

:이 문자열에 숫자가 포함되어 있습니까?

def contains_number(str)
  str =~ /[0-9]/
end

contains_number("The year is 2015")  # returns 12
contains_number("The cat is black")  # returns nil
<블록 인용>

기억하세요:`=~`를 사용할 때 반환 값은 문자열 인덱스 또는 `nil`입니다.

문자 범위를 지정하기 위한 좋은 약식 구문이 있습니다.

  • \w [0-9a-zA-Z_]와 동일합니다.
  • \d [0-9]과(와) 동일합니다.
  • \s 공백과 일치 (탭, 일반 공백, 줄 바꿈)

다음과 같은 부정적인 형태도 있습니다.

  • \W [0-9a-zA-Z_]에 없는 모든 것
  • \D 숫자가 아닌 모든 것
  • \S 공백이 아닌 모든 것

점 문자 . 새 줄을 제외한 모든 것과 일치합니다. 리터럴 .를 사용해야 하는 경우 그러면 탈출해야 합니다.

:특수 문자 이스케이프

# If we don't escape, the letter will match
"5a5".match(/\d.\d/)

# In this case only the literal dot matches
"5a5".match(/\d\.\d/) # nil
"5.5".match(/\d\.\d/) # match

수정자

지금까지는 한 번에 하나의 문자만 일치시킬 수 있었습니다. 여러 문자를 일치시키기 위해 패턴 수정자를 사용할 수 있습니다.

수정자 설명
+ 1개 이상
* 0 이상
? 0 또는 1
{3,5} 3에서 5 사이

지금까지 배운 모든 것을 결합하여 더 복잡한 정규 표현식을 만들 수 있습니다.

:IP 주소처럼 보이나요?

# Note that this will also match some invalid IP address
# like 999.999.999.999, but in this case we just care about the format.

def ip_address?(str)
  # We use !! to convert the return value to a boolean
  !!(str =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)
end

ip_address?("192.168.1.1")  # returns true
ip_address?("0000.0000")    # returns false

정확한 문자열 일치

정확한 일치가 필요한 경우 다른 유형의 수정자가 필요합니다. 제가 무슨 말을 하는지 알 수 있도록 예를 들어보겠습니다.

# We want to find if this string is exactly four letters long, this will
# still match because it has more than four, but it's not what we want.
"Regex are cool".match /\w{4}/

# Instead we will use the 'beginning of line' and 'end of line' modifiers
"Regex are cool".match /^\w{4}$/

# This time it won't match. This is a rather contrived example, since we could just
# have used .size to find the length, but I think it gets the idea across.

모든 라인이 아니라 문자열의 시작 부분에서 엄격하게 일치하려면(\n 뒤) ) \A를 사용해야 합니다. 및 \Z ^ 대신 및 $ .

캡처 그룹

캡처 그룹을 사용하면 일치 항목의 일부를 캡처하고 나중에 다시 사용할 수 있습니다. 매치를 캡처하기 위해 캡처하려는 부분을 괄호로 묶습니다.

:로그 파일 파싱

Line = Struct.new(:time, :type, :msg)
LOG_FORMAT = /(\d{2}:\d{2}) (\w+) (.*)/

def parse_line(line)
  line.match(LOG_FORMAT) { |m| Line.new(*m.captures) }
end

parse_line("12:41 INFO User has logged in.")
# This produces objects like this:
# 

이 예에서는 .match를 사용하고 있습니다. =~ 대신 .

이 메서드는 MatchData를 반환합니다. 일치하는 항목이 있으면 개체, 그렇지 않으면 nil입니다. MatchData 클래스에는 유용한 방법이 많이 있습니다. 자세한 내용은 설명서를 확인하세요!

부울 값만 원하는 경우(true / false ) 그런 다음 match?를 사용할 수 있습니다. Ruby 2.4부터 사용할 수 있는 메서드입니다. 이것은 match보다 빠릅니다. Ruby는 MatchData를 생성할 필요가 없기 때문에 개체.

.captures를 사용하여 캡처된 데이터에 액세스할 수 있습니다. 메소드 또는 MatchData 처리 배열과 같은 개체의 경우 0 인덱스에는 전체 일치 항목이 포함되고 결과 인덱스에는 일치하는 그룹이 포함됩니다.

첫 번째 캡처 그룹을 원하는 경우 다음을 수행할 수 있습니다.

m = "John 31".match /\w+ (\d+)/

m[1]
# 31

캡처하지 않는 그룹을 가질 수도 있습니다. 성능 저하 없이 표현식을 그룹화할 수 있습니다. 복잡한 표현식을 읽기 쉽게 만드는 데 유용한 명명된 그룹을 찾을 수도 있습니다.

구문 설명
(?:...) 비 캡처 그룹
(?<foo>...) 명명된 그룹

:명명된 그룹

m = "David 30".match /(?\w+) (?\d+)/
m[:age]
# => "30"
m[:name]
# => "David"

명명된 그룹은 MatchData를 반환합니다. 결과를 읽기 위해 액세스할 수 있는 개체입니다.

앞을 내다보고 뒤를 돌아보세요

이것은 모든 정규식 구현에서 사용할 수 없는 고급 기술입니다. Ruby의 정규식 엔진은 이를 수행할 수 있으므로 이를 활용하는 방법을 살펴보겠습니다.

미리보기를 통해 특정 경기가 전후에 있는지 살짝 살펴보겠습니다.

이름 설명
(?=pat) 긍정적인 전망
(?<=pat) 긍정적인 비하인드
(?!pat) 부정적 예측
(? 네거티브 룩비하인드

:적어도 하나의 문자가 앞에 오는 숫자가 있습니까?

def number_after_word?(str)
  !!(str =~ /(?<=\w) (\d+)/)
end

number_after_word?("Grade 99")

Ruby의 정규식 클래스

Ruby 정규식은 Regexp의 인스턴스입니다. 수업. 대부분의 경우 이 클래스를 직접 사용하지는 않지만 알아두면 좋습니다. 🙂

puts /a/.class
# Regexp

한 가지 가능한 사용은 문자열에서 정규식을 만드는 것입니다.

regexp = Regexp.new("a")

정규 표현식을 만드는 또 다른 방법:

regexp = %r{\w+}

정규식 옵션

정규 표현식에 몇 가지 옵션을 설정하여 다르게 작동하도록 할 수 있습니다.

옵션 설명
루비 정규식 대소문자를 구분하지 않음
m 점은 개행과 일치
x 공백 무시

이 옵션을 사용하려면 /를 닫은 후 정규식 끝에 문자를 추가합니다. .

좋아요 :

"abc".match?(/[A-Z]/i)

긴 정규 표현식 서식 지정

복잡한 Ruby 정규식은 읽기 어려울 수 있으므로 여러 줄로 나누면 도움이 됩니다. 'x' 수식어를 사용하여 이를 수행할 수 있습니다. 이 형식을 사용하면 정규식 내에서 주석을 사용할 수도 있습니다.

:

LOG_FORMAT = %r{
  (\d{2}:\d{2}) # Time
  \s(\w+)       # Event type
  \s(.*)        # Message
}x

Ruby 정규식:모두 합치기

정규식은 다양한 Ruby 메서드와 함께 사용할 수 있습니다.

  • .split
  • .스캔
  • .gsub
  • 및 기타...

:.scan을 사용하여 문자열의 모든 단어 일치

"this is some string".scan(/\w+/)
# => ["this", "is", "some", "string"]

:문자열에서 모든 숫자 추출

"The year was 1492.".scan(/\d+/)
# => ["1492"]

:문자열의 모든 단어를 대문자로

str = "lord of the rings"

str.gsub(/\w+/) { |w| w.capitalize }
# => "Lord Of The Rings"

:이메일 주소 확인

email = "[email protected]"

!!email.match(/\A[\w.+-]+@\w+\.\w+\z/)

# true

이 마지막 예제는 !!를 사용합니다. 결과를 부울 값으로 변환(true / false ) 또는 match?를 사용할 수 있습니다. 이미 이 작업을 수행하는 Ruby 2.4+의 메서드이며 더 빠릅니다.

결론

정규식은 훌륭하지만 때로는 약간 까다로울 수 있습니다. rubular.com과 같은 도구를 사용하면 ruby regex를 빌드하는 데 도움이 됩니다. 더 인터랙티브한 방식으로. Rubular에는 또한 매우 유용할 Ruby 정규식 치트 시트가 포함되어 있습니다. 이제 편집기를 열고 코딩을 시작할 차례입니다!

아, 잊지 마세요. 공유 재미있게 보셨다면 더 많은 분들이 배울 수 있도록 친구들과 함께 🙂