Adicionando texto a um arquivo 2 linhas antes da última correspondência de padrão

1

Eu preciso adicionar uma string de várias linhas em TEXT em myfile.txt onde encontrar o texto # My Search .

Se fosse uma substituição padrão regular, então sed com i faria o truque. No entanto, eu não sei como ir 2 linhas acima da partida em sed .

Exemplo, myfile.txt :

text1
text2
#
# My Search
#
text4
text5
#
# My Search
#
text6

TEXT se parece com:

TEXT="
[my search]
home=/var/home
string=random

"

myfile.txt deve olhar para o final:

text1
text2
#
# My Search
#
text4
text5

[my search]
home=/var/home
string=random

#
# My Search
#
text6
    
por Nir 21.11.2018 / 09:37

3 respostas

0

Use grep -n para extrair o número da linha e usá-lo em um endereço sed para inserir o texto, que precisa ser colocado corretamente, ou seja, deve haver uma barra invertida antes de cada nova linha:

line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
((--line))
text=${TEXT//$'\n'/$'\\n'}
text=${text%$'\\n'}$'\n'

sed "$line i \
$text" myfile.txt
    
por 21.11.2018 / 10:32
0

tac + bash (substituição de variável) + abordagem GNU sed :

txt_reversed=$(echo "$TEXT" | tac)
tac myfile.txt \
| sed -e "N;N;N; s~#\n# My Search\n#~&${txt_reversed//$'\n'/\n}\n~" | tac

A saída:

text1
text2
#
# My Search
#
text4
text5

[my search]
home=/var/home
string=random

#
# My Search
#
text6
    
por 21.11.2018 / 10:41
0

A maneira mais fácil de fazer isso de uma só vez é usar uma ferramenta que pode pesquisar para trás, ed é uma delas. O ideal seria ter o texto salvo em um arquivo (por exemplo, insert.txt ) e inserir o conteúdo do arquivo duas linhas antes da última ocorrência de PATTERN , para que você pudesse executar:

ed -s infile <<\IN
.t.
?PATTERN?-2r insert.txt
$d
,p
q
IN

Ele encontra a última ocorrência de PATTERN , sobe outras 2 lines e r eads em insert.txt . Em seguida, ele imprime o conteúdo do buffer via ,p . Substitua por w se você quiser editar o arquivo no local.

Com outras ferramentas que não podem pesquisar para trás um two-pass é o caminho a percorrer: 1º passo - obter o número da linha e 2º passo - inserir o conteúdo do texto após a linha NR-2 ou antes da linha NR-1 . Para textos salvos em uma variável, eu prefiro awk sobre outras ferramentas que dependem de regex (a última requer o pré-processamento do texto a ser inserido para escapar de qualquer caractere especial: há vários que precisam ser salvos, não apenas a nova linha , dependendo da técnica usada):

export TEXT
awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
{if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile
    
por 21.11.2018 / 12:10