Como substituir um texto específico em um bloco de texto por um valor de outro arquivo?

0

Eu tenho um bloco de linhas de texto repetidas:

I love banana  
I love mango  
I love papaya  
I love guava  
I love peaches  
I love baby  
I love watermelon  
I love banana  
I love mango  
I love papaya  
I love guava  
I love peaches  
I love baby  
I love watermelon  
I love banana  
I love mango  
I love papaya  
I love guava  
I love peaches  
I love baby  
I love watermelon  
I love banana
I love mango  
I love papaya  
I love guava  
I love peaches  
I love baby  
I love watermelon  
I love banana  
I love mango  
I love papaya  
I love guava  
I love peaches  
I love baby  
I love watermelon  

Eu tenho outro arquivo com o seguinte texto:

D1  
D2  
D3  
D4  
D5  

É necessário que, sempre que o termo baby seja encontrado, seja repassado pelo termos seqüenciais no segundo arquivo. Por exemplo, para o primeiro baby , ele é substituído como:

I love D1  

Para o segundo baby , ele é substituído como D2 e assim por diante até o final do arquivo. Abaixo, apresentamos o resumo das tentativas feitas sem sucesso (mencionadas de maneira extremamente casual ... apliques para isso). Alguém pode me ajudar por favor?

for x in 'cat test1.txt|tr -d '\r''; do awk '{gsub(/baby/,'"$x"')}' test3.txt ; done

for x in 'cat test1.txt|tr -d '\r''; do sed -i 's/baby/$x/g' test3.txt ; done

sed "0,/baby/{s/baby/$x/}" "test3.txt"  

for x in 'cat test1.txt|tr -d '\r''; do awk 'NR==1,/baby/{sub(/baby/,'"$x"')} print' test3.txt ; done  
awk '/^baby$/&&getline<"test1.txt"||1' test3.txt

awk 'NR==FNR{Arr[NR]=$0;next}{if($0==baby){i++;print Arr[i]}else{print}}' test3.txt test1.txt

#!/bin/bash

while read -r line; do  
    if [[ "$line"  == baby ]]; then  
        sed -n '1p' test3.txt  
        sed -i".bup" '1d' test3.txt   
    else  
        echo "$line"  
    fi    
done < test1.txt
    
por crusader 25.05.2018 / 10:44

3 respostas

2

Se tiver certeza de que o número de linhas em file2.txt é maior que o número de vezes quebaby aparece, um script simples pode ser usado:

awk 'BEGIN{ sf="file2.txt"}
     /baby/ {  getline var <sf; gsub(/baby/,var,$0) }
print
' file1.txt

Mas um script muito mais robusto que ambos verificam se a leitura de file2.txt obteve algum erro ou retrocesso no início, se o script chegar ao final do arquivo2.txt:

awk 'BEGIN{ sf="file2.txt"}
/baby/{
         # If at the end of second file, rewind to start.
         while( (test=(getline var <sf)) != 1 ){
            if( test==-1 ){ print "Error: file ",sf,":",ERRNO; exit 1 }
            if( test==0  ){ close(sf); continue }
                # This script should never get up to here
                print "Unexpected error"; exit 2
            }
         sub(/baby/,var ,$0)
     }
1
' file1.txt

Se file2.txt contiver apenas quatro linhas D1, D2, D3, D4, você receberá:

$ ./script
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D1
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D2
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D3
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D4
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D1
I love watermelon
    
por 25.05.2018 / 12:07
1

Outro awk

awk -v f='file2' '$3=="baby"{getline $3 <f}1' file1

Cada vez que field3 = baby no arquivo1 substitui $ 3 por uma linha de arquivo2.

Editar:

Se eu entendi bem, sua linha no arquivo1 se parece com:

Ilovepeaches
Ilovemybeautifulbabygirl
Ilovewatermelon

E você quer substituir cada bebê por uma linha do arquivo2

Então, você pode tentar desta maneira:

awk -v search='baby' -v f='file2' '
  $0 ~ search {
     split($0,lign,search)
     getline <f
     $0=lign[1]$0lign[2]
}1' file1

saída:

Ilovepeaches
IlovemybeautifulD3girl
Ilovewatermelon
    
por 25.05.2018 / 11:57
0

Com awk, file2 contendo o texto de substituição e file1 o texto repetido:

awk 'FNR == NR {baby[NR] = $0; next} /baby/ {count++; $NF = baby[count]} 1'  file2 file1

Observe que file2 é o primeiro argumento de arquivo aqui, não file1 .

Explicação:

  • FNR == NR é verdadeiro para o primeiro arquivo lido por awk, então file2 here. Para esse arquivo, salvamos cada linha em uma matriz, indexada por um número de linha
  • Para o segundo arquivo, mantemos um count de cada linha correspondente a baby e obtenha a entrada da matriz para essa contagem e substitua o último campo por essa entrada.

Eu recebo a saída como:

~ awk 'FNR == NR {baby[NR] = $0; next} /baby/ {count++; $NF = baby[count]} 1'  file2 file1
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D1
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D2
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D3
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D4
I love watermelon
I love banana
I love mango
I love papaya
I love guava
I love peaches
I love D5
I love watermelon
    
por 25.05.2018 / 11:36

Tags