Теперь по делу.
Операционная система у меня ubuntu ++ постоянно по работе приходится сидеть в консоли. Очень часто возникает задача, быстро по шаблону поменять что то в файле. Ответ на вскидку = sed. В свое время я читал про него, но понял что при помощи perl могу делать то же самое. Прошло время, sed я забыл совершенно, а вот perl тоже стал забываться, и я постоянно не могу найти пример однострочных скриптов.
Теперь по порядку.
Задача:
Дано.
Есть файл xx.txt в котором лежат числа от 1-го до 5-ти, каждое число, новая строка.
cd@laptop:~/data/tmp$ cat xx.xx
1
2
3
4
5
Нужно:
Хочется заменить все вхождения строки 3 на что то свое, пусть это будет строка "hello"
Решение:
cd@laptop:~/data/tmp$ perl -ig -ne 's/3/hello/;print $_; ' xx.xx
cd@laptop:~/data/tmp$ cat xx.xx
1
2
hello
4
5
Или
cd@laptop:~/data/tmp$ perl -ig -pe 's/3/hello/; ' xx.xx
cd@laptop:~/data/tmp$ cat xx.xx
1
2
hello
4
5
cd@cd-acer:~/data/tmp$ ls *g
9.jpg xx.xxg
Объяснение.
perl позволяет запускать однострочные скрипты, не создавая файл с кодом скрипта.
Пример:
cd@laptop:~/data/tmp$ perl -e 'print "test\n"'
test
cd@laptop:~/data/tmp$
За это отвечает опция -e после которой идет код для выполнения.
Однострочные скрипты, после кода, могут принимать параметром файл, а также, можно заставить выполнять код указанный -e для каждой строки.
Пример:
cd@laptop:~/data/tmp$ perl -ne "print ;" xx.xx
1
2
hello
4
5
Т.е. в данном случае мы попросили перл, выполнить распечатку строки по умолчанию, а т.к. была указана опция -n то это команда применялась к каждой строке файла xx.xx, т.е. получили cat
Также существует параметр -p, который после выполнения кода распечатывает строку. Т.е. логично что команда вида
perl -ne "dosmth; print $_;" file
будет аналогична
perl -pe "dosmth" file
Ну а теперь завершая. Мы добились того, что можем выполнять любые операции над каждой строкой в файле, и печатать это в stdout, однако первоначальная постановка задачи, звучала как замена строк в файле на лету. Именно для этого и существует опция -i
т.е.
perl -i -pe "dosmth" file
выполнит код dosmth для отдельно взятой строки и заменит ее в указанном файле.
опция -i может принимать необязательный параметр, и тогда, скрипт перед началом работы сделает backup копию файла
Пример.
cd@laptop:~/data/tmp/1$ perl -ibak -ne 'print;' 1.txt
cd@laptop:~/data/tmp/1$ ls
1.txt 1.txtbak
cd@laptop:~/data/tmp/1$ cat 1.txt
1
2
3
cdlaptop:~/data/tmp/1$ cat 1.txtbak
1
2
3
cd@laptop:~/data/tmp/1$
Теперь само решение должно быть понятно, а также понятно почему я привел два варианта.
Upd:
Появилась простая задачка, в одном из конфигов нужно увеличивать на единицу одно из значений, пусть условно это будет номер билда.
Возьмем пример файла конфига
cd:$ cat config
Key1 Value2
build=projectname.005
one more line
Допустим нам нужно получить такой же конфиг но с build=projectnam.006
perl -i -pe 's/(projectname\.)(\d+)/sprintf("%s%03d", $1, $2+1)/e' config
Пояснения.
-i -pe объяснялось выше.
Что изменилось? В конце регулярного выражения добавился флаг e, который означает что правая часть выражения будет выполняться как код perl и только после выполнения результат подставится для замены.
Можно было бы конечно сделать что то вроде
perl -pe 's/(projectname\.)(\d+)/$1 . ($2+1)/e' config
Key1 Value2
build=projectname.6
one more line
! опция -i была убрана, я хотел чтобы файл не менялся, а результат был в output
Как видим пропадают два ведущих нуля, именно поэтому была использована функция sprintf
4 comments:
Спасибо. Пригодилось :)
Если нет возражений, я дала на Ваш блог ссылку в своем http://aal-blog.blogspot.com/2009/10/stroka1-stroka2.html
Без проблем. Рад хоть что то пригодилось.
Есть вопрос...
Возможно ли запуская скрипт дать ему на обработку данные.
Например запускаю скрипт совмещения двух баз там идёт запрос месяцев... потом передача вывода на печать ...
тоесть хотелось бы чтоб данные поступали в скрипт с запуском...
Заранее спасибо
D *nix точно можно, насчет винды не знаю.
Возьмем пример из статьи
cd@cd-acer:/tmp$ perl -ig -ne 's/3/hello/;print $_; ' xx.xx
В данном случае однострочный скрипт натравлен на файл, вам же хочется натравить скрипт на STDOUT вывод какой то команды.
Возьмем для примера команду
$cat 1.txt
1
2
3
4
5
cat печатает файл в STDOUT, теперь натравливаем наш скрипт на вывод этой команды через pipe
cd@cd-acer:/tmp$ cat 1.txt | perl -ig -ne 's/3/hello/;print $_; '
1
2
hello
4
5
Почитайте http://ru.wikipedia.org/wiki/Перенаправление_(UNIX)#.D0.9A.D0.BE.D0.BD.D0.B2.D0.B5.D0.B9.D0.B5.D1.80.D1.8B
Post a Comment