zsh: использование разных СИМВОЛОВ СЛОВА для слова-аннулирования и слова вперед/назад

the output of the replacement is leaving the lines unchanged

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

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

Просто удалили замену, и неудивительно, что нет никакой разницы с тем, что вы получили сначала, это не соответствует вводу.

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

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES.*;//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

Все еще не соответствует, теперь единственными специальными символами являются (), которые, вероятно, следует экранировать:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES.*;//" currencies.rb
> 

Да, это соответствует -наш ввод был сопоставлен и удален, поэтому давайте снова добавим конечный бит, на этот раз также экранируя другие ()s:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb
> 

Все еще совпадает, так что давайте снова добавим замену:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
> currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')

Хм, кажется, это неправильная часть. Это связано с тем, что & заменяется всем совпадающим выражением, а не одной подгруппой, вместо которой вы хотите $1, $2и т. д.:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$2) || Currency.new(:code => '\$2')/" currencies.rb
> currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')

Почти готово, отсутствуют некоторые кавычки -нам также не нужны совпадения двух других подгрупп, поэтому давайте удалим их:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\$1') || Currency.new(:code => '\$1')/" currencies.rb 
> currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')

Вот и все, именно то, что мы хотели.

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

1
24.08.2019, 10:46
1 ответ

Вы можете bindвиджеты vi-{back,for}ward-blank-wordна Ctrl+{влево, вправо}`:

bindkey $'\E[1;5D' vi-backward-blank-word
bindkey $'\E[1;5C' vi-forward-blank-word

или переопределить {back,for}ward-wordвиджеты, чтобы использовать другой WORDCHARS(, чтобы это повлияло на другие привязки (, такие как Alt+{B,F} ), которые используют эти виджеты):

WORDCHARS='~!#$%^&*(){}[]<>?.+;-'
MOTION_WORDCHARS='~!#$%^&*(){}[]<>?.+;-/'

''{back,for}ward-word() WORDCHARS=$MOTION_WORDCHARS zle.$WIDGET
zle -N backward-word
zle -N forward-word

См. такжеinfo zsh select-word-styleструктуру для динамического выбора стилей слов .

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

autoload -U select-word-style
zle -N select-word-style
bindkey '\ez' select-word-style

WORDCHARS='~!#$%^&*(){}[]<>?.+;-' # for the "normal" style
select-word-style normal
zstyle ':zle:*ward-word' word-style space
zstyle ':zle:backward-kill-word' word-style space

Вы получите стиль слова на основе «пробела» -для виджетов *ward-wordи backward-kill-wordи всего, что выбрано с помощью Alt+Z , изначально «обычный»,$WORDCHARS-на основе стиля слова для других виджетов слова.

8
27.01.2020, 23:22

Теги

Похожие вопросы