Parece que você deseja inserir o conteúdo desse arquivo após a última ocorrência de <path start="process_
.
Você poderia fazer:
awk '
/path start="process_/ {print saved $0; saved=""; n++; next}
n {saved = saved $0 RS; next}
{print}
END{system("cat tmp.xml"); printf "%s", saved}' process.xml
Embora isso signifique armazenar a parte do arquivo da última ocorrência de path start="process_
para o final na memória.
Ou você pode sorver os arquivos inteiros na memória com:
perl -0777 -pe 's/.*path start="process_.*?\n\K/<STDIN>/se
' process.xml < tmp.xml
Uma variante que verifica o </fork>
na próxima linha não vazia:
perl -0777 -pe 's{.*path start="process_[^\n]*\n\K(?=\s*</fork>)}{<STDIN>}se
' process.xml < tmp.xml
Uma variante que alinha o recuo e adiciona um caractere de nova linha extra se estiver faltando em tmp.xml
:
perl -0777 -pe 's{(?s:.*)(^\h*).*path start="process_.*\n\K(?=\s*</fork>)}{
$insert = <STDIN>;
$indent = $1;
$insert =~ s/^/$indent/gm;
$insert =~ s/\n?$/\n/;
$insert}me' process.xml < tmp.xml
Com -0777 -pe 'code' file
, perl
executa o code
, com $_
sendo o conteúdo do file
e imprime esse $_
(aqui modificado pelo code
) posteriormente.
Lá, temos apenas um comando de substituição s{pattern}{replacement}flags
.
O truque para obter a última ocorrência do padrão em todos esses comandos é o principal ganancioso .*
(aqui sob o s
flag, para que ele também corresponda aos caracteres de nova linha). Como ele é ganancioso, ele tentará corresponder tantos caracteres até ^
(um começo de linha com o m
flag) seguido por uma sequência de espaços em branco horizontais ( \h*
), que capturamos em $1
with (\h*)
seguido por nosso padrão seguido pelo resto da linha ( .*
desta vez sem o s
flag, então não irá engolir os caracteres de nova linha) seguido por uma nova linha.
Depois disso, adicionamos um \K
para informar perl
que é o início do texto correspondente. Em seguida, temos um operador de look ahead para verificar se essa nova linha é seguida por uma sequência de espaço em branco ( \s*
) e </fork>
.
Na substituição, nós tomamos o conteúdo de tmp.xml
do stdin e inserimos o recuo capturado no início de cada uma de suas linhas, adicionamos a nova linha à direita se estiver faltando e oferecemos isso como substituto.
Uma alternativa poderia ser processar o arquivo duas vezes. Uma vez para recuperar o número da linha da última ocorrência do padrão, e o segundo para inserir o arquivo lá:
sed "$(awk '/path start="process_/{n=NR};END{print n}' < process.xml
)r tmp.xml" process.xml
Como alternativa, talvez você possa simplesmente inseri-lo antes de </fork>
:
awk '/<\/fork>/{system("cat tmp.xml")};1' < process.xml