Страница 1 из 1

Замена многострочного фрагмента sed

Добавлено: 2010-10-05 18:02:44
Dmitriy_K
Кто-нибудь может подсказать как построить регулярное выражение для поиска sed такого блока из нескольких строк?

Код: Выделить всё

8) TERM=ansi-lwp; export TERM
   BASEDIR=/home/dir ; export BASEDIR
        . $BASEDIR/.setup
        cd $BASEDIR
        TERM=ansi-lwp; export TERM
        prog copy
        exit
        ;;

q) echo ; echo "Goodbye, "`logname`" !"
У меня как-то не проходит конструкция с символами переноса строки "\n". Что-то не так делаю.

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-05 18:31:11
Dmitriy_K
Кое-что смог сделать, строки фрагмента находятся (к сожалению, не как единое целое). Но теперь не могу их заменить единым блоком, всё время или заменяется построчно или не работает.

Код: Выделить всё

sed -ne '/8) TERM=ansi-lwp.*/,/q)/ s/.*$/OK/p' test.txt
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-05 21:27:45
Нефиг_чем_заняться
На awk подойдет ?

Код: Выделить всё

#! /bin/sh

s='jljkj kjlkj kl
kljkljkljkl jkl
kljkljklj
fghfghfhf
8) TERM=ansi-lwp; export TERM
   BASEDIR=/home/dir ; export BASEDIR
        . \$BASEDIR/.setup
        cd \$BASEDIR
        TERM=ansi-lwp; export TERM
        prog copy
        exit
        ;;

q) echo ; echo "Goodbye, "`logname`" !"
11111
tretretrr uiy uihjnmbc ntr d j
yutyu  g786  ihjkhp9ujo.
12121212'


echo "${s}" | awk 'BEGIN {
    a="8\) TERM\=ansi\-lwp\; export TERM";                         # start block
    b="q\) echo \; echo \"Goodbye\, \".*\" \!\""                   # end block
    c="replace block-first line\nreplace block-second line\n"   # replace block
    RS=a
}
/a/,/b/ { print c;}'

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-05 22:57:01
Dmitriy_K
Большое спасибо! Сейчас попробую.
У меня почти получилось скриптом на sed:

Код: Выделить всё

#!/bin/sh

ZAM=`cat zam.txt`    #Многострочный текст на замену блока. В нём приходится предварительно экранировать все символы regex и выставлять "\" на концах строк.

/usr/bin/sed -ne "/8) TERM=ansi-lwp.*/,/q)/ s/.*/$ZAM/p" test.txt
Но отрабатывает он пока странно: выдаёт три замены подряд вместо одной, как хотелось бы.

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-05 23:33:32
Dmitriy_K
Да, скрипт на awk отрабатывает, спасибо! Пока только не могу придумать как сделать, чтобы он менял только нужный фрагмент текста, а не заменял весь текст.
Остаётся загадкой почему неправильно отрабатывает замена в sed. Пробовал проверить как отрабатывает поиск фрагмента для замены.

Код: Выделить всё

sed -ne "/8) TERM=ansi-lwp.*/,/q)/ s/.*/&/p" test.txt

8) TERM=ansi-lwp; export TERM
   BASEDIR=/home/dir ; export BASEDIR
        . \$BASEDIR/.setup
        cd \$BASEDIR
        TERM=ansi-lwp; export TERM
        prog copy
        exit
        ;;

q) echo ; echo "Goodbye, "`logname`" !"
Оказалось, всё правильно, находится только один нужный фрагмент. Почему же тогда замена вставляется три раза подряд? :st:
...А заменять нужно срочно в около 4тыс. файлов.

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-05 23:52:20
Dmitriy_K
Кажется, получилось, наконец. :Yahoo!:

Код: Выделить всё

/usr/bin/sed -ne "/8) TERM=ansi-lwp.*/,/q)/ s/.*\" !\"/$ZAM/p" test.txt
Оказалось, надо было regexp замены фрагмента дописать, как в конце последней строки фрагмента, и кавычки заэкранировать.
Но за awk всё равно спасибо!

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-06 2:51:17
Dmitriy_K
В конечном счёте настрогал такую штуку: :smile:

Код: Выделить всё

#!/bin/sh

ZAM=`cat zam.txt`

#Change dir for "find ." to "find /home/" etc.
#
(find . -name ".bash_profile_old*" -exec /usr/bin/grep -le '^while.*8 \]$' '{}' +) > changed_bash_profiles.txt

#Change ".bash_profile_old*" to ".bash_profile"
#
for i in `find . -type f -name ".bash_profile_old*" | xargs grep -le '^while.*8 \]$' | awk -F: '{print $1}'`
do
cp ${i} ${i}_1
/usr/bin/sed -i '' -e 's/^while.*8 \]$/while \[ "$i" != 1 -a "$i" != 2 -a "$i" != 3 -a "$i" != 4 -a "$i" != q -a "$i" != Q -a "$i" != 5 -a "$i" != 6 -a "$i" != 7 -a "$i" != 8 -a "$i" != 10 \]/' \
-e 's/echo "8).*(\/prog_dir2\/dbcopy)"$/echo "8) Punkt of menu (\/prog_dir2\/dbcopy)"\
echo "10) New punkt of menu"/' \
-e 's/^if \[ "\$i".*8 \]$/if [ "$i" != 1 -a "$i" != 2 -a "$i" != 3 -a "$i" != 4 -a "$i" != q -a "$i" != Q  -a "$i" != 5 -a "$i" != 6 -a "$i" != 7 -a "$i" != 8 -a "$i" != 10 ]/' \
-e "/8) TERM=ansi-lwp.*/,/q)/ s/.*\" !\"/$ZAM/" \
${i}
done
Естественно, тут дан пример тестового, полностью безопасного скрипта.
В zam.txt требуется вставить текст нужно дополнительного многострочного фрагмента с заэкранированными символами regexp.
Надеюсь, ещё кому пригодится, а то я совсем не смог найти ни одного примера замены многострочного фрагмента текста.

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-06 7:25:00
Нефиг_чем_заняться
Ни ФИГА себе !!!

Не, так не годится...

Код: Выделить всё

#! /bin/sh
##########################
# User defined variables
#-------------------------

srcfile='./srctest.txt'  # source file
outfile='./replaced.txt' # output file
zamena='./zamena.txt'    # file that contain replacement text

beginBlock='8\\) TERM\\=ansi.*'                # start string of text block that would be replaced. Should be the Regular expression.
endBlock='q\\) echo \\; echo \\"Goodbye\\,.*'  # end string of text block that would be replaced. Should be the Regular expression.

#
######################
# No user intervention beyond this point !!!!!!!!!
######################

cat "${srcfile}" | awk -v replace="${zamena}" -v a="${beginBlock}" -v b="${endBlock}" 'BEGIN {
    c=""; x=1;
    while (x != 0 && x != -1) {
        x=getline < replace
        if (x != 0) c=c $0 "\n";
    }
    if (x == -1) { print "Error while reading file: " replace "  Exiting..."; exit 1; }
}
{   if ( $0 ~a && skip == 0) { skip=1; print c; }
    if ( $0 ~b && skip == 1) { skip=0; next; }
}!skip' > "${outfile}"

exit 0
Правте заголовок в User defined variable для входного файла, файла с заменой и выходной файл ONLY. И не надо ничего нигде экранировать, усё будет пучком.
Сорри, что не SED-e, но меня достают куча его s,p,d и прочие сокращения, awk он как то ближе к человеческому языку

Re: Замена многострочного фрагмента sed

Добавлено: 2010-10-06 11:43:26
Dmitriy_K
Да, круто! :smile: :cz2:
Спасибо большое ещё раз!