Substitui todas as ocorrências de uma string encontrada em um arquivo usando valores de outro arquivo

0

Eu tenho um arquivo CSV ( data.csv ) como abaixo:

apple_val, balloon_val, cherry_val, dog_val
1         ,5           ,6          ,7
3         ,19          ,2          ,3

Eu tenho um arquivo de texto ( sentence.txt ) como abaixo:

I have apple_val apple(s) and balloon_val balloons. My dog_val dogs were biting the cherry_val cherries. 

Eu quero o meu arquivo de saída ( output.txt ) como abaixo:

I have 1 apple(s) and 5 balloons. My 7 dogs were biting the 6 cherries.
I have 3 apple(s) and 19 balloons. My 3 dogs were biting the 2 cherries. 

Eu usei o script abaixo. Mas meu script é específico para o exemplo acima.

awk -F "," {print $1, $2, $3, $4} data.csv | while read a, b, c,d
do
    sed -e "s/apple_val/$a/g" -e "s/balloon_val/$b/g" -e "s/dog_val/$d/g" -e "s/cherry_val/$c/g" sentence.txt >> output.txt
done

Eu quero torná-lo genérico lendo a primeira linha do arquivo CSV (o cabeçalho) e substituindo as ocorrências dessas cadeias (como apple_val) no arquivo de texto.

Como posso fazer isso?

    
por Aarthi 17.09.2015 / 06:42

2 respostas

2

Variante modificada alienth (as matrizes são usadas):

#!/bin/bash
tr -s ',' ' ' <data.csv | {
read -a tokens
while read -a values; do
    for index in $(seq 0 $((${#tokens[*]}-1))); do
        echo "s/${tokens[$index]}/${values[$index]}/g"
    done | sed -f - sentence.txt
done
}

Mesmo com awk :

awk -F"[, ]+" '
NR == FNR{
    s=s $0 "\n"
    next}
FNR == 1{
    for(i=1;i<=NF;i++)
        val[i]=$i
    next}
{
    p=s
    for(i=1;i<=NF;i++)
        gsub(val[i], $i, p)
    printf p}
' sentence.txt data.csv
    
por 17.09.2015 / 09:39
2

O que você está tentando fazer aqui é conhecido como 'modelo', e fazer seus próprios modelos está sempre repleto de buracos inesperados:)

Aqui está um script de shell que fará o que você está pedindo, mas não é bonito e provavelmente é bem frágil. Eu recomendo enfaticamente uma solução de templates mais robusta.

#!/bin/bash

sentence=$(cat sentence.txt)

tokens=$(head -n1 data.csv | cut -d, -f1- --output-delimiter="")

cat data.csv | tail -n +2 | while read i; do
    token_number=0
    new_sentence=$sentence
    for token in $tokens; do
        let token_number+=1
        value=$(echo $i | cut -d, -f${token_number})
        new_sentence=$(echo $new_sentence | sed -e "s/${token}/${value}/g")
    done
    echo $new_sentence
done

Saída do resultado, dada a entrada que você especificou na pergunta:

I have 1 apple(s) and 5 balloons. My 7 dogs were biting the 6 cherries.
I have 3 apple(s) and 19 balloons. My 3 dogs were biting the 2 cherries.
    
por 17.09.2015 / 07:09