LinuxForum.Fans
Тема

sed-скрипт работающий напрямую с файлом по типу ключа -i

Автор: valet 11 сообщений 5070 просмотров
#301492

Ребята, выручайте, гуглю вторые сутки подряд, ничего не наггугливается. маны тоже читал...

Задача заставить sed-скрипт изменять входной файл (edit in place), уточняю - именно скрипт (не однострочный вызов sed из командной строки с ключом -i)

text
valet@valet-comp:~/test$ cat file
foo
valet@valet-comp:~/test$ cat script 
#!/bin/sed -rf

s~foo~bar~ valet@valet-comp:~/test$ ./script file bar valet@valet-comp:~/test$ cat file foo

file - файл в котором надо сделать правки, в даном простоейшом примере заменить foo на bar
script - sed-скрипт, который должен это сделать, естественно без конструкции типа ./script file > temp && mv temp file

Предполагаю что можно добавить какой-то ключик в первую строку sed-скрипта, чтобы получалось то что я хочу. Но не знаю какой. Пробовал #!/bin/sed -i -rf - не работает.

Подскажите пожалуйста, кто хорошо знает sed.

П.С. sed -ri 's~foo~bar~' file не предлашать из-за того что в моей реальной задаче нет возможности использовать однострочник с вызовом sed из командной строки по причине того что стоит задача вставлять счетчик liveinternet - а там куча спецсимволов, которые непонятно как экранировать да и попробуй все заэкранируй, а в случае использования кода в sed-скрипте все работает без экранирования (единственное разрыв строки приходится менять на \n), вот только не хотелось бы городить велосипеды с копированием с темп-файла, хотелось бы чтобы скрипт сразу менял входной файл.

#301549

Не, ну я sed не знаю, поэтому могу предложить как-то так:

text

#!/bin/bash

sed -i 's/foo/bar/' $1

:)

#301555

"-=Serj=-" написал:
Не, ну я sed не знаю, поэтому могу предложить как-то так:
ну я же говорю так не подходит :)
Вместо bar у меня в реальности код счетчика liveinternet с кучей спецсимволов и заэкранировать их все не удается. А вот если такой bar в sed-скрипте все работает без экранирования.
#301557
"valet" написал:
код счетчика liveinternet с кучей спецсимволов

пример в студию.

#301579

Ок, тогда реальный пример.
Вот код счетчика:

text
<!--LiveInternet counter--><script type="text/javascript"><!--\ndocument.write("<a href='http://www.liveinternet.ru/click;nazvanie-sajta' "+\n"target=_blank><img src='//counter.yadro.ru/hit;nazvanie-sajta?t14.6;r"+\nescape(document.referrer)+((typeof(screen)=="undefined")?"":\n";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?\nscreen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+\n";h"+escape(document.title.substring(0,80))+";"+Math.random()+\n"' alt='' title='LiveInternet: показано число просмотров за 24"+\n" часа, посетителей за 24 часа и за сегодня' "+\n"border='0' width='88' height='31'><\/a>")\n//--></script><!--/LiveInternet-->\n

надеюсь парсер ничего не съел :)

Его надо вставить в html-страницу перед тегом </body>, то есть по факту заменить в файле вхождение </body> на <счетчик></body>.

Теперь коды:
Самый простой вариант написать sed-скрипт такой:

text
#!/bin/sed -rf

s~</body>~<!--LiveInternet counter--><script type="text/javascript"><!--\ndocument.write("<a href='http://www.liveinternet.ru/click;nazvanie-sajta' "+\n"target=_blank><img src='//counter.yadro.ru/hit;nazvanie-sajta?t14.6;r"+\nescape(document.referrer)+((typeof(screen)=="undefined")?"":\n";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?\nscreen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+\n";h"+escape(document.title.substring(0,80))+";"+Math.random()+\n"' alt='' title='LiveInternet: показано число просмотров за 24"+\n" часа, посетителей за 24 часа и за сегодня' "+\n"border='0' width='88' height='31'><\/a>")\n//--></script><!--/LiveInternet-->\n</body>~gi

Тогда можно применить

text
./script file.html > temp && cp temp file.html

Вот рабочее отображение этого процесса:

text
valet@valet-comp:~/snippets/python_test$ cat file.html 
</body>
valet@valet-comp:~/snippets/python_test$ ./script file.html > temp && cp temp file.html 
valet@valet-comp:~/snippets/python_test$ cat file.html 
<!--LiveInternet counter--><script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click;nazvanie-sajta' "+
"target=_blank><img src='//counter.yadro.ru/hit;nazvanie-sajta?t14.6;r"+
escape(document.referrer)+((typeof(screen)=="undefined")?"":
";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
";h"+escape(document.title.substring(0,80))+";"+Math.random()+
"' alt='' title='LiveInternet: показано число просмотров за 24"+
" часа, посетителей за 24 часа и за сегодня' "+
"border='0' width='88' height='31'></a>")
//--></script><!--/LiveInternet-->
</body>

И все правильно работает. Но так как файлов таких для обработки 100500, не хотелось бы делать лишние операции копирования в темп-файл и из него в исходный.

Я бы хотел что-то типа:

text
./script file.html

Обработать так сказать "edit in place" то что мог бы сделать ключ -i при запуски из консоли. Но из-за сложности счетчика и обилия спецсимволов в коде я не могу привести этот код в формат:

text
sed -ri 's~</body>~счетчик</body>~'
#301580

#!/bin/sed -rif
или
valet@valet-comp:~/test$ sed -rif script
тут r может быть и не нужно...

#301584

"Fat-Zer" написал:
#!/bin/sed -rifилиvalet@valet-comp:~/test$ sed -rif script тут r может быть и не нужно...
нет, так не работает.
Но каким-то волшебным образом работает так:
text
sed -r -i -f script file.html

это в случае если sed-скрипт оформить без первой строки, то есть сразу команды, в моем случае так:

text
valet@valet-comp:~/snippets/python_test$ cat script 
s~</body>~<!--LiveInternet counter--><script type="text/javascript"><!--\ndocument.write("<a href='http://www.liveinternet.ru/click;nazvanie-sajta' "+\n"target=_blank><img src='//counter.yadro.ru/hit;nazvanie-sajta?t14.6;r"+\nescape(document.referrer)+((typeof(screen)=="undefined")?"":\n";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?\nscreen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+\n";h"+escape(document.title.substring(0,80))+";"+Math.random()+\n"' alt='' title='LiveInternet: показано число просмотров за 24"+\n" часа, посетителей за 24 часа и за сегодня' "+\n"border='0' width='88' height='31'><\/a>")\n//--></script><!--/LiveInternet-->\n</body>~gi
valet@valet-comp:~/snippets/python_test$ cat file.html 
</body>
valet@valet-comp:~/snippets/python_test$ sed -r -i -f script file.html 
valet@valet-comp:~/snippets/python_test$ cat file.html 
<!--LiveInternet counter--><script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click;nazvanie-sajta' "+
"target=_blank><img src='//counter.yadro.ru/hit;nazvanie-sajta?t14.6;r"+
escape(document.referrer)+((typeof(screen)=="undefined")?"":
";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
";h"+escape(document.title.substring(0,80))+";"+Math.random()+
"' alt='' title='LiveInternet: показано число просмотров за 24"+
" часа, посетителей за 24 часа и за сегодня' "+
"border='0' width='88' height='31'></a>")
//--></script><!--/LiveInternet-->
</body>
valet@valet-comp:~/snippets/python_test$ 
#301585

Это какая-то фантастика - всегда просто писал скрипты с заголовком #!/bin/sed -rf, а оказывается не надо!

#301596
text

alexander@goblin-book ~ $ echo foo >1 && sed -ri -f ./1.sed 1 && cat 1
bar-oo
alexander@goblin-book ~ $ echo foo >1 && ./1.sed -i 1 && cat 1
bar-oo
alexander@goblin-book ~ $ cat 1.sed
#!/bin/sed -rf
s/f(o+)/bar-\1/
"valet" написал:
Это какая-то фантастика - всегда просто писал скрипты с заголовком #!/bin/sed -rf, а оказывается не надо!

это нужно только если не указываешьинтерпритатор при вызове...

#301597

"Fat-Zer" написал:
alexander@goblin-book ~ $ echo foo >1 && sed -ri -f ./1.sed 1 && cat 1
bar-oo
alexander@goblin-book ~ $ echo foo >1 && ./1.sed -i 1 && cat 1
bar-oo
alexander@goblin-book ~ $ cat 1.sed
#!/bin/sed -rf
s/f(o+)/bar-\1/
Это что еще за велосипеды? :)
#301598
"valet" написал:
Это что еще за велосипеды?

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

Войдите или зарегистрируйтесь, чтобы ответить.