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

멋진 루비 정규식 트릭

나는 루비에서 정규 표현식으로 할 수 있는 다른 멋진 트릭을 보고 정규 표현식 조건에 대한 어제 기사를 따라가는 것이 재미있을 것이라고 생각했습니다.

정규 표현식을 통한 문자열 분할

텍스트 구분 기호를 사용하여 문자열을 분할하는 방법은 매우 익숙할 것입니다.

"one,two".split(",")
# => ["one", "two"]

그러나 split도 정규식을 허용한다는 것을 알고 계셨습니까?

# use `,` and `-` as delimiters
"one,two-three".split(/,|-/)
=> ["one", "two", "three"]

# Use comma as thousands separator for US currency,
# but use a space for Euros
"1,000USD".split /(?=.*(USD))(?(1),| )/

구분자 캡처

여기에 깔끔한 파티 트릭이 있습니다. 일반적으로 문자열을 분할하면 구분 기호가 사라집니다.

# The commas vanish!
"one,two".split(",")
# => ["one", "two"]

그러나 정규식을 사용하고 구분 기호를 그룹 안에 넣으면 split 구분 기호도 캡처합니다.

"one,two-three".split(/(,|-)/)
=> ["one", ",", "two", "-", "three"]

이것이 발생하는 이유는 split 실제로 각 캡처 그룹의 경계에서 문자열을 분할합니다.

악용 split

split을 남용할 수 있습니다. 거의 match처럼 작동하도록 . 아래 코드에서는 정규식에 4개의 그룹을 사용하여 문자열을 4개로 분할합니다.

"1-800-555-1212".split(/(1)-(\d{3})-(\d{3})-(\d{4})/)
=> ["", "1", "800", "555", "1212"]

정규식은 전체 소스 문자열과 일치하므로 결과 배열의 첫 번째 항목은 빈 문자열입니다.

글로벌 매칭

기본적으로 정규식은 패턴과 한 번만 일치합니다. 아래 코드에서는 5개의 가능한 일치 항목이 있음에도 불구하고 하나의 일치 항목만 얻습니다.

"12345".match /\d/
=> #<MatchData "1">

Perl과 같은 다른 언어에서 해결책은 정규 표현식을 "전역"으로 표시하는 것입니다. Ruby에는 해당 옵션이 없지만 String#scan이 있습니다. 방법.

scan 메서드는 모든 일치 항목을 포함하는 배열을 반환합니다.

"12345".scan /\d/
=> ["1", "2", "3", "4", "5"]

편리한 블록 구문도 있습니다.

"12345".scan /\d/ do |i|
  puts i
end

불행히도 문자열을 느리게 스캔하는 방법은 없는 것 같습니다. 따라서 이 기술은 500MB 파일을 처리하는 데 적합하지 않을 수 있습니다.

그룹으로 스캔

이제 이 시점에서 스캔에서 그룹을 사용하여 어떤 종류의 이상한 트릭을 할 수 있는지 궁금하기를 바랍니다.

불행히도 여기에서의 행동은 완전히 예측 가능하고 지루합니다. 그룹 결과 다차원 배열:

"hiho hiho".scan /(hi)(ho)/
=> [["hi", "ho"], ["hi", "ho"]]

이상한 경우가 하나 있습니다. 그룹을 사용하는 경우 그룹에 없는 항목은 반환되지 않습니다.

"hiho hiho".scan /(hi)ho/
=> [["hi"], ["hi"]]

속기

=~에 대해 알고 계실 것입니다. 정규식이 문자열과 일치하는지 여부를 확인하는 방법입니다. 일치가 시작되는 문자의 인덱스를 반환합니다.

"hiho" =~ /hi/
# 0
"hiho" =~ /ho/
# 2

하지만 경기를 확인하는 또 다른 빠른 방법이 있습니다. ===에 대해 이야기하고 있습니다. 운영자.

/hi/ === "hiho"
# true

a === b를 작성할 때 루비에서는 "b가 다음에 의해 정의된 집합에 속합니까?"라고 묻고 있습니다. 또는 이 경우 "'hiho'는 정규식 /hi/과 일치하는 문자열 집합에 속합니까? ".

=== 연산자는 Ruby의 case 문에서 내부적으로 사용됩니다. 즉, case 문에서도 정규식을 사용할 수 있습니다.

case "hiho"
when /hi/
  puts "match"
end

삼중 등호 연산자는 고유한 메서드가 정규식이나 문자열을 허용하도록 하는 데에도 유용할 수 있습니다.

무시할 미리 구성된 클래스 목록에 없는 경우를 제외하고 오류가 발생할 때 일부 코드를 실행하고 싶다고 상상해 보십시오. 아래 예에서는 ===를 사용합니다. 연산자를 사용하여 사용자가 문자열 또는 정규식을 지정할 수 있습니다.

def ignored?(error)
  @ignored_patterns.any? { |x| x === error.class.name }
end

바로 그것입니다!

확실히 Ruby와 Rails에는 이와 같은 수십 가지의 작은 트릭이 흩어져 있습니다. 특히 마음에 드는 것이 있으면 알려주세요!