2016-01-20 2 views
1

У меня есть функция, translate(), принимает несколько параметров. Первые пары являются единственным обязательными и является строкой, что я всегда завернуть в одинарных кавычках, например:regex для первого экземпляра определенного символа, который НЕ приходит сразу после другого определенного символа

translate('hello world');

Другого PARAMS не являются обязательным, но могут быть включены как это:

translate('hello world', true, 1, 'foobar', 'etc');

И сама строка может содержать спасся одинарные кавычки, например:

translate('hello\'s world');

Теперь я хочу искать все файлы кода для всех экземпляров этого вызова функции и извлекать только строку. Для этого я придумал следующий grep, который возвращает все между translate (' и либо '), либо ',. Почти идеально:

grep -RoPh "(?<=translate\(').*?(?='\)|'\,)" .

Проблема с этим, хотя, является то, что если вызов что-то вроде этого:

translate('hello \'world\', you\'re great!');

Мой Grep будет возвращать только это:

hello \'world\

Так что я хочу изменить это, чтобы часть, которая в настоящее время выглядит s для «) или », вместо ищет первое вхождение ", что не сбежали, т.е. не сразу следуют \

Надеюсь, я смысл. Любые предложения, пожалуйста?

+0

Предполагая, что строка не заканчивается сбежавшего обратной косой черты, вы можете использовать отрицательное в 'назад положительный предпросмотр -?.?) * (=' '(<= \ (перевод \) | (? https://regex101.com/r/wD6oL6/1 –

+0

@JoshCrozier: Что, если строка заканчивается беглым обратным слэшем? –

+0

Что-то по строкам '(? <= Translate \ (') (\\' | [^ ']) *' должно делать трюк. –

ответ

2

Вы можете использовать этот grep с PCRE регулярное выражение:

grep -RoPh "\btranslate\(\s*\K'(?:[^'\\\\]*)(?:\\\\.[^'\\\\]*)*'" . 

Here is a regex demo

RegEx Распад:

\b   # word boundary 
translate  # match literal translate 
\(   # match a (
\s*   # match 0 or more whitespace 
\K   # reset the matched information 
'    # match starting single quote 
(?:   # start non-capturing group 
    [^'\\\\]* # match 0 or more chars that are not a backslash or single quote 
)    # end non-capturing group 
(?:   # start non-capturing group 
    \\\\.  # match a backslash followed by char that is "escaped" 
    [^'\\\\]* # match 0 or more chars that are not a backslash or single quote 
)*   # end non-capturing group 
'    # match ending single quote 

Вот версия без \K с использованием просмотровых обходные:

grep -oPhR "(?<=\btranslate\(')(?:[^'\\\\]*)(?:\\\\.[^'\\\\]*)*(?=')" . 

RegEx Demo 2

+0

Люблю деталь здесь, но это, кажется, не возвращает никаких результатов К сожалению, все равно! – Ric

+0

[См. то же самое 'grep' здесь] (http://ideone.com/AItN9q) – anubhava

+0

Хм, странно. Ваш вывод там выглядит идеально, но я не могу получить то же самое от реального дерева файлов, используя # grep -RoPh "\ btranslate \ (\ s * \ K '(?: [^' \\\\] *) (?: \\\\. [^ '\\\\] *) *'". – Ric

0

Я думаю, что проблема является .*? части: ? делает его нежадный узор, то есть он будет кратчайшей строкой, которая соответствует шаблону. По сути, вы говорите: «Дайте мне кратчайшую строку, за которой следуют цитата + close-paren или quote + comma». В вашем примере «world\» следует за одной цитатой и запятой, поэтому она соответствует вашему шаблону. В этих случаях, я хотел бы использовать что-то вроде следующего рассуждения:

Строка цитата, ноль или больше символов, и цитата: '.*'

Персонаж является все, что не цитата (потому что цитата завершает строку): '[^']*'

За исключением того, что вы можете поместить цитату в строку, экранируя ее обратным слэшем, поэтому символ либо «обратный слэш, за которым следует цитата», либо, если это не так », quote ": '(\\'|[^'])*'

Положите все это на Gether и вы получите

grep -RoPh "(?<=translate\(')(\\'|[^'])*(?='\)|'\,)" .