Примените подстановку регулярных выражений глобально ко многим файлам с помощью скрипта - PullRequest
7 голосов
/ 12 июля 2010

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

Я пробовал sed, но обрабатывать более одной строки за раз неудобно, особенно если нет ограничений на количество строк, которые могут соответствовать шаблону.

Я также попробовал этот скрипт (на одном файле, для тестирования):

ex $1 <<EOF
gs/,\(\_\s*[\]})]\)/\1/
EOF

Шаблон удалит запятую в любом списке в стиле Perl / Ruby, так что «[a, b, c,]» будет выглядеть как «[a, b, c]», чтобы удовлетворить Internet Explorer. , который один среди браузеров, задыхается в таких списках.

Шаблон прекрасно работает в vim, но ничего не делает, если я запускаю его в ex, как указано выше.

Кто-нибудь может увидеть, чего мне не хватает?

Ответы [ 5 ]

12 голосов
/ 15 июля 2010

Вы попросили скрипт, но упомянули, что вы пользователь vim. Я склонен выполнять поиск и замену всего проекта внутри vim, например:

:args **/*.js | argdo %s/,\(\_\s*[\]})]\)/\1/ge | update

Это очень похоже на решение :bufdo, упомянутое другим комментатором, но оно будет использовать ваш список аргументов, а не ваш buflist (и, следовательно, не требует совершенно новой сессии vim, и вы не должны быть осторожны с закрытием буферов ты не хочешь трогать).

  • :args **/*.js - устанавливает ваш arglist для хранения всех файлов .js в этом каталоге и подкаталогах
  • | - pipe является разделителем команд vim, что позволяет нам иметь несколько команд в одной строке
  • :argdo - выполнить следующие команды для всех аргументов. это "проглотит" последующие трубы
    • % - диапазон, представляющий весь файл
    • :s - команда замены, о которой вы уже знаете
    • :s_flags, ge - глобальный (подставлять столько раз, сколько возможно для каждой строки) и подавлять ошибки (т. Е. "Нет совпадений")
    • | - этот канал "проглатывается" :argdo, поэтому следующая команда также действует один раз для аргумента
    • :update - как :write, но только после изменения буфера

Этот шаблон, очевидно, будет работать для любой команды vim, которую вы хотите запустить для нескольких файлов, поэтому следует помнить о ней. Например, мне нравится использовать его для удаления конечных пробелов (%s/\s\+$//), установки одинаковых концов строк (set ff=unix) или кодировки файлов (set filencoding=utf8) и retab моих файлов.

5 голосов
/ 12 июля 2010

1) Откройте все файлы с помощью vim:

bash$ vim $(find . -name '*.js')

2) Применить команду замены ко всем файлам:

:bufdo %s/,\(\_\s*[\]})]\)/\1/ge

3) Сохраните все файлы и выйдите:

:wall
:q

Я думаю, вам нужно перепроверить ваш шаблон поиска, он выглядит неправильно. Я думаю, где у вас \_\s* вы должны иметь \_s* вместо.

Редактировать: Вы также должны использовать опции /ge для команды :s... (я добавил их выше).

3 голосов
/ 13 июля 2010

Вы можете автоматизировать действия как vi, так и ex, передав аргумент +'command' из командной строки, что позволяет использовать их в качестве текстовых фильтров.

В вашей ситуации следующая команда должна работать нормально:

find /path/to/dir -name '*.js' | xargs ex +'%s/,\(\_\s*[\]})]\)/\1/g' +'wq!'

1 голос
/ 12 июля 2010

вы можете использовать комбинацию команды find и sed

find /path -type f -iname "*.js" -exec sed -i.bak 's/,[ \t]*]/]/' "{}" +;
0 голосов
/ 12 июля 2010

Если вы работаете в Windows, Notepad ++ позволяет запускать простые регулярные выражения для всех открытых файлов.

Поиск ,\s*\] и замена на ]

должны работать для описанных вами типов списков.

...