Использование цитирования ANSI-C в sed - PullRequest
1 голос
/ 26 октября 2010

У меня есть файл с именем "insert.txt". Это может выглядеть так (или уродливее):

ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>

И я хочу заменить блок текста в целевом файле (target.txt), который разделен «STARTSTACKOVERFLOW» на «STOPSTACKOVERFLOW». (Здесь я немного упрощаю вопрос, но он тот же).

Сценарий bash, который я использую для этого:

TARGETFILE=target.txt
SOURCEFILE=insert.txt
SOURCETXT="$(<$SOURCEFILE)"
DELIMTXT=$(printf "%q" "$SOURCETXT")

sed -i -e "/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/cSTARTSTACKOVERFLOW\n\n${DELIMTXT}\n\nSTOPSTACKOVERFLOW\n" $TARGETFILE

Проблема в том, что то, что вставлено в "target.txt", на самом деле соответствует ANSI-C:

$'ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>'

Обратите внимание на добавленный $ ''.

Причина в том, что printf "% q" создает этот стиль цитирования. Я хотел бы избежать этого - хотя и нужно, потому что я должен избежать всего дурного в этом файле.

Есть ли лучший способ сделать это, используя bash и sed?

1 Ответ

0 голосов
/ 26 октября 2010

POSIX sed имеет команду 'r' для чтения из файла. Итак:

sed -i -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/r large.txt' target.txt

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

sed -i -e '/STOPSTACKOVERFLOW/r large.txt' \
       -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/d' target.txt

Простая демонстрация

Эта версия удаляет начальный и конечный маркеры.

$ cat data
sdasas
adsasdas
start
more
more
end
sdasda
sdasdad
$ cat replace
replace1
replace2
replace3
$ sed -e '/^end$/r replace' -e '/start/,/end/d' data
sdasas
adsasdas
replace1
replace2
replace3
sdasda
sdasdad

Сохранение начального и конечного маркеров

$ cat sedfile
/^end$/{
a\
start
r replace
a\
end
}
/^start$/,/^end$/d
$ sed -f sedfile data
sdasas
adsasdas
start
replace1
replace2
replace3
end
sdasda
sdasdad
$ 

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

...