Соответствующая строка между двумя маркерами, которые являются путями к файлам и содержат специальные символы - PullRequest
1 голос
/ 06 июня 2019

Я пытаюсь написать скрипт ruby, который будет возвращать текст между двумя другими строками. Проблема заключается в том, что две соответствующие строки содержат специальные символы. Выход из специальных символов не решает проблему.

Я попытался избежать специальных символов, различных шаблонов сопоставления и предоставить переменные с соответствующими строками без особой удачи.

Я также протестировал упрощенное сопоставление, используя только ODS и NAME в качестве разделителей. Это, похоже, сработало.

####Example contents of logfile 
#### 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'

log_to_scan = 'logfile'
marker1 = 'ODS | FILENAME = /tmp/'
marker2 = ' | NAME'

contents = File.read(log_to_scan)

print contents.match(/ODS \| FILENAME = \/tmp\/(.*) \| NAME/m[1].strip

print contents.match(/marker1(.*)marker2/m)[1].strip

Учитывая приведенное выше примерное содержимое, я ожидаю, что результат будет bbbbbb. Однако я получаю либо ничего, либо ошибку NoMethod. Не уверен, что еще до истины или какую ошибку я совершаю.

Ответы [ 3 ]

3 голосов
/ 06 июня 2019
str = 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'
marker1 = 'ODS | FILENAME = /tmp/'
marker2 = ' | NAME'

r = /(?<=#{Regexp.escape(marker1)}).*(?=#{Regexp.escape(marker2)})/i
  #=> /(?<=ODS\ \|\ FILENAME\ =\ \/tmp\/).*(?=\ \|\ NAME)/i 
str[r]
  #=> "bbbbbb" 

или

r = /#{Regexp.escape(marker1)}(.*)#{Regexp.escape(marker2)}/i
str[r,1]
  #=> "bbbbbb" 

или, если известно, что сопоставляемая строка записана в нижнем регистре, или допустимо вернуть строку в нижнем регистре:

s = str.downcase
  #=> "aaaaaaaaa ods | filename = /tmp/bbbbbb | name = ccccc" 
m1 = marker1.downcase
  #=> "ods | filename = /tmp/" 
m2 = marker2.downcase
  #=> " | name" 
id1 = s.index(m1) + m1.size
  #=> 32
id2 = s.index(m2, id1+1) - 1
  #=> 37
str[id1..id2]
  #=> "bbbbbb"

См. Regexp :: escape . В № 1

(?<=#{Regexp.escape(marker1)})

- это позитивный взгляд за , требующий, чтобы marker1 появился непосредственно перед матчем.

(?=#{Regexp.escape(marker2)})

- это позитивный прогноз , требующий marker2 для немедленного отслеживания матча.

В # 3 я использовал форму String # index , которая принимает второй аргумент ("смещение").

2 голосов
/ 06 июня 2019

Ваше оригинальное выражение в порядке, мы бы немного его изменили, если в строковом входе могут быть другие дополнительные пробелы, и оно может работать:

^.+?ODS(\s+)?\|(\s+)?FILENAME(\s+)?=(\s+)?\/tmp\/(.+?)(\s+)?\|(\s+)?NAME(\s+)?=(\s+)?(.+?)$

и наши желаемые результаты находятся в этих двух группах захвата:

(.+?)

Тест

re = /^.+?ODS(\s+)?\|(\s+)?FILENAME(\s+)?=(\s+)?\/tmp\/(.+?)(\s+)?\|(\s+)?NAME(\s+)?=(\s+)?(.+?)$/mi
str = 'aaaaaaaaa ODS | Filename = /tmp/bbbbbb | NAME = ccccc'

# Print the match result
str.scan(re) do |match|
    puts match.to_s
end

Демо

1 голос
/ 06 июня 2019

Как насчет String#scanf?

> require 'scanf'
> str = 'ODS | FILENAME = /tmp/ | NAME'
> str.scanf('ODS | FILENAME = %s | NAME')
=> ["/tmp/"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...