Заменить шаблон в файле содержимым другого файла

20

У меня есть текстовый файл ( devel.xml).

Я добавил слово REPLACETHIS, чтобы заменить эту строку содержимым другого файла ( temp.txt).

Самое близкое, что у меня есть, это:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

Это вставляет содержимое после строки, а затем удаляет строку после.

Это лучший способ сделать это?

RafaelGP
источник
Должен ли он быть sed? В зависимости от того, сколько текста в temp.txt, я могу перейти к Perl-решению.
user17591

Ответы:

34

То, что вы сделали, это удалите все, SUBSTITUTETHISчто появляется в файле (но не остальную часть строки, где он появляется), и вставьте содержимое temp.TXTниже этой строки. Если SUBSTITUTETHISв строке появляется несколько раз, удаляется только первое вхождение и temp.TXTдобавляется только одна копия .

Если вы хотите заменить всю строку при SUBSTITUTETHISпоявлении, используйте dкоманду. Так как вам нужно запустить оба, rи dкогда есть совпадение, поместите их в группу в скобках.

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

Некоторые реализации sed позволяют вам использовать точки с запятой для разделения команд и вообще не использовать разделители вокруг фигурных скобок, но вам все еще нужен символ новой строки для завершения аргумента rкоманды:

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

Если вы хотите заменить SUBSTITUTETHISсодержимым файла, но сохранить то, что находится до и после него в строке, это более сложно. Самый простой способ - включить содержимое файла в команду sed; обратите внимание, что вам придется правильно цитировать его содержимое.

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

Или используйте Perl. Это коротко, но выполняется catодин раз для каждой замены:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

Чтобы прочитать файл один раз при запуске сценария и избежать зависимости от команды оболочки:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

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

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt
Жиль "ТАК - перестать быть злым
источник
Как я мог изменить команду perl, чтобы вместо cat temp.txtменя можно было это сделать cat ${variable}?
Мария Инес Парнисари
@MariaInesParnisari Я ошибся с форматированием комментариев. Смотрите мой ответ, с немного другим, более надежным решением.
Жиль "ТАК - перестань быть злым"
Поскольку File :: Slurp не всегда устанавливается, альтернативой является использование -0777переключателя для slurp во всем файле и обычного open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk
Как r temp.TXTпереносить сообщения типа «BEGIN temp.TXT», «END temp.TXX»
kyb
Я нашел решение для моего вопроса. Используйте a(добавить) команду. grymoire.com/Unix/Sed.html#uh-36
kyb