2017-02-20 9 views
3

У меня есть строка, которая будет содержать одно из следующих действий текста:Извлечение файла и без оканчивающихся символов

  1. рядных; имя файла = "name.extension";
  2. inline; filename = "name.extension"
  3. inline; имя файла = 'name.extension';
  4. inline; filename = 'name.extension'
  5. inline; имя файла = name.extension;
  6. inline; имя файла = name.extension

Я хочу, чтобы извлечь name.extension и может обрабатывать первые 5 случаев, но я не могу понять, как сделать все случаи с одним регулярным выражением. Все, что я пробовал, становится слишком жадным. Возможно ли это?

Регулярное выражение, которое работает в течение первых 5 является:

/filename=["']?(.*)(?=["']?;)/ 

name.extension находится в первой группе захвата и должен позволить любой действительный символ для имени файла в Linux. Это включает в себя "и" и, в ней

Спасибо за любую помощь

+0

Ни один из ответов пока не идентифицирует несбалансированные кавычки, такие как одиночная кавычка раньше и без цитат. Вы хотите, чтобы метод подтвердил, что цитата, если она присутствует, сбалансирована? –

+0

Собственно, это будет вишня на торте :-) – Whyves

+0

В определенный момент вам нужна грамматика. – Schwern

ответ

3

Сделайте это в три этапа.

  1. Разделить на ;, чтобы разделить выписки.
  2. Разделите пару ключ/значение на =.
  3. Сделка с цитированием значения.

Вот пример.

def get_value(line) 
    # Split into statements 
    statements = line.split(/\s*;\s*/) 

    # Extract the value of the 2nd statement 
    _,value = statements[1].split(/\s*=\s*/) 

    # Strip the quotes 
    value.gsub!(/^(['"]?)(.*)\1$/, '\2') 

    return value 
end 

Есть несколько случаев с краями, которые не обрабатываются: что, если заявление, которое вас интересует, не второе? Но это может быть исправлено по мере необходимости. Гораздо легче улучшить ваш синтаксический анализ, когда это делается несколькими шагами, а не пытаться втиснуть его в одно регулярное выражение.

Например, это правильно обрабатывает встроенные и экранированные котировки, такие как %q[inline; filename="name's.extension"] и %q[inline; filename="name's.\\"extension\\""].


Если вы действительно хотите сделать это как одно регулярное выражение, хорошо, вы его попросили.

re =/
    \bfilename 
    \s*=\s* 
    (?: 
     (?<quote>['"])(?<value>.*)\k<quote> | 
     (?<value>[^;]+) 
    ) 
/x 
return re.match(line)['value'] 

Это разделяет обработку удлинителя на две альтернативы: одна с кавычками и одна без. В противном случае filename=name.ext; подберет точку с запятой, и я не смогу найти другой способ остановить ее, что не приведет к новой проблеме.

Например, /\bfilename\s*=\s*(?<quote>['"]?)(?<value>.*?)\k<quote>;?$/ будет работать с тестовыми данными, но тогда это не удастся, если после точки с запятой есть что-то вроде %q[inline; filename='name.extension'; foo].

Вы запросили экспертное знание регулярного выражения. Частью эксперта по регулярному выражению является знать, когда вы не должны использовать регулярное выражение. Это, вероятно, должно быть обработано грамматикой, или вы будете постоянно преследовать краевые случаи.

+0

Да, я мог бы решить это с помощью кода, но мне было очень интересно узнать, может ли кто-то с экспертным знанием regex решить эту проблему. Если ответ заключается в том, что регулярное выражение не может охватить все случаи, я вернусь к программированию. Я пытаюсь исправить что-то в paperclip, и самым простым было бы просто исправить регулярное выражение. – Whyves

+0

@Whyves Я редактировал это с помощью одного регулярного выражения, но, как вы можете видеть, это отвратительно. Если вы имеете в виду это [скрепка] (https://github.com/thoughtbot/paperclip), я не понимаю, почему вы не можете заменить регулярное выражение вызовом функции. Возможно, вы должны задать вопрос о том, что вы пытаетесь исправить. – Schwern

+0

Хорошо, вы сделали свой тон громким и ясным :-) Я действительно верю в удобочитаемость и техническую поддержку. Однако я должен сказать WOW для регулярного выражения. Что касается скрепки, это не проблема, я буду использовать функцию. Дело в том, что его текущая обработка заголовка «content-disposition» ошибочна, поскольку я столкнулся с краевым случаем. В настоящее время он обрабатывается с помощью регулярного выражения, поэтому самым простым способом было бы исправить эту единственную строку кода. Большое спасибо за время и энергия, которая вошла в этот ответ! – Whyves

2

Попробуйте это:

/filename=["']?([^"';]+)/ 

Она должна возвращать строку в первой группе захвата

[ 
    'inline; filename="name.extension";', 
    'inline; filename="name.extension"', 
    "inline; filename='name.extension'", 
    "inline; filename='name.extension';", 
    "inline; filename=name.extension;", 
    "inline; filename=name.extension" 
].map { |str| str[/filename=["']?([^"';]+)/, 1] == "name.extension" } 

=> [true, true, true, true, true, true] 
+0

Это работает на заданном множестве, но не выполняется во внутренних котировках типа '% q [inline; filename = "name's.extension"] ' – Schwern

+0

Вот почему это затрудняет (по крайней мере, для меня). Я не контролирую имя файла, и поэтому он может содержать одиночные или двойные кавычки, а также точку с запятой. Вот почему я использовал позитивный взгляд, но он не справляется с одним случаем. – Whyves

1
.!.

Держите его простым и удобным в обслуживании, не используйте регулярное выражение:

arr = %q(inline; filename="name.extension"; 
inline; filename="name.extension" 
inline; filename='name.extension'; 
inline; filename='name.extension' 
inline; filename=name.extension; 
inline; filename=name.extension).lines.map(&:chomp) 

p arr.map{|str| str.delete(%q("';)).split("=").last} 

Это использует гибкий строковый литерал синтаксиса Ruby; трюк% q() используется здесь 2 раза, обеспечивая беспроблемную обработку одиночных и двойных кавычек.

+0

Это исключает любые встроенные цитаты типа 'inline; filename = "name's.extension"; 'или' inline; filename = "name. \" extension \ ""; ' – Schwern

+0

@Schwern да, но AFAIK в любом случае сомнительны в именах файлов. – steenslag

+0

Это нарушает принцип [Robustness] (https://en.wikipedia.org/wiki/Robustness_principle). Поскольку кавычки удалены, это может быть даже проблема безопасности, оставляющая открытие, чтобы обмануть процесс чтения другого файла. – Schwern

 Смежные вопросы

  • Нет связанных вопросов^_^