найти и заменить в файле - PullRequest
0 голосов
/ 18 марта 2011

У меня есть требование для поиска шаблона, который выглядит примерно так:

timeouts = {default = 3.0; };

и замените его на

timeouts = {default = 3000.0;.... }; 

т.е. умножить время ожидания на коэффициент 1000.

Есть ли способ сделать это для всех файлов в каталоге

EDIT :

Обратите внимание, что некоторые файлы являются символическими ссылками в каталоге. Есть ли способ сделать это также для символических ссылок?

Обратите внимание, что тайм-ауты существуют как подстрока и в файлах, поэтому я хочу убедиться, что заменяется только эта строка. Любое решение приемлемо при использовании sed awk perl.

Ответы [ 4 ]

1 голос
/ 18 марта 2011

Попробуйте:

for f in *
do
    sed -i 's/\(timeouts = {default = [0-9]\+\)\(\.[0-9]\+;\)\( };\)/\1000\2....\3/' "$f" 
done

Это сделает замены на месте для каждого файла в текущем каталоге. В некоторых версиях sed требуется расширение для резервного копирования после параметра -i. Вы можете поставить один такой:

sed -i .bak ...

Некоторые версии не поддерживают редактирование на месте. Вы можете сделать это:

sed '...' "$f" > tmpfile && mv tmpfile "$f"

Обратите внимание, что это, очевидно, фактически не умножение на 1000, поэтому, если число равно 3.1, оно станет "3000.1" вместо 3100.0.

0 голосов
/ 18 марта 2011

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

  • Все ли эти скрипты имеют схожую функциональность?
  • Можете ли вы создать модуль, который они все будут использовать для общих подпрограмм?
  • В модуле, вы могли бы иметь одну строку, которая позволила бы иметь множитель?

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

0 голосов
/ 18 марта 2011

вы можете сделать это

perl -pi -e 's/(timeouts\s*=\s*\{default\s*=\s*)([0-9.-]+)/print $1; $2*1000/e' *
0 голосов
/ 18 марта 2011
$ perl -pi.bak -e 's/\w+\s*=\s*{\s*\w+\s*=\s*\K(-?[0-9.]+)/sprintf "%0.1f", 1000 * $1/eg' *

Примечания:

  • Регулярное выражение соответствует только числу (см. \K в perlre)
  • /e означает, что замена оценивается
  • Я включаю sprintf в замену на тот случай, если вам нужен более точный контроль над форматированием
  • Perl -i может работать с кучей файлов

РЕДАКТИРОВАТЬ

Было отмечено, что некоторые файлы являются шамболическими ссылками.Учитывая, что этот процесс не идемпотентен (запускать его дважды для одного и того же файла плохо), вам лучше сгенерировать уникальный список файлов на случай, если одна из ссылок указывает на файл, который появляется в другом месте списка.Вот пример с find, хотя код уже существующего списка должен быть очевиден.

$ find -L . -type f -exec realpath {} \; | sort -u | xargs -d '\n' perl ...

(Предполагается, что ни одно из ваших имен файлов не содержит символ новой строки!)

...