2017-02-09 11 views
0

Я пытался использовать sed в последнее время, чтобы сгенерировать кучу методов из разделяемых разделяемых запятой и новой линией элементов перечисления. Я побежал в следующем поведение, которое кажется неинтуитивным:Почему sed соответствует чему-то вне группы в составе группы?

$ echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g' 
"Hi Hello,!" 

Здесь я пытаюсь захватить все до запятой в группу с помощью \(.*\), то я позволяю опциональную запятую ,\?. Я ожидал, что это заменит \1 всем до первой запятой, а именно Hello, но по какой-то причине запятая также включается в замещение, хотя она не находится внутри группы. Почему это так?

ответ

1

Регулярные выражения по умолчанию содержат жадные соответствия (слева направо), backtracking, если самое жадное совпадение не работает. Так что в случае с \(.*\),\?, самое жадное совпадение должно соответствовать Hello, - \(.*\) и ничего для ,\?.

Я не уверен, как делать нежелательное соответствие в основных регулярных выражениях (что и используется sed). В регулярных выражениях в стиле Perl (не используется sed) вы помещаете вопросительный знак после оператора сопоставления, поэтому вы должны использовать что-то вроде (.*?),?.

Следующее, что вы можете сделать, это использовать что-то вроде \([^,]*\),\?, но затем оно прекратит совпадение в первой запятой, которую он видит.

1

Это потому, что sed Regex жадный, а квантователь ? означает, что в этом случае 0 или 1 предыдущего токена - ,.

Итак, здесь двигатель жадно подходит до конца, а так как ? изготовлен по заказу ?, он также входит в группу захваченных (.*).

Чтобы получить желаемое поведение, падение ?:

% echo 'Hello,' | sed 's/\(.*\),\?/"Hi \1!"/g' 
"Hi Hello,!" 

% echo 'Hello,' | sed 's/\(.*\),/"Hi \1!"/g' 
"Hi Hello!" 
+0

Спасибо за ответы. Запятая в конце должна быть необязательной, потому что я пытаюсь совместить с членами перечисления, а последний не имеет конечной запятой. –

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

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