Замените все вхождения строки, найденной в файле, используя значения из другого файла

У меня есть файл CSV ( data.csv ), как data.csv ниже:

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

У меня есть текстовый файл ( sentence.txt ), как показано ниже:

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

Мне нужен выходной файл ( output.txt ), как output.txt ниже:

 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. 

Я использовал приведенный ниже сценарий. Но мой сценарий специфичен для приведенного выше примера.

 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 

Я хочу сделать его общим, читая первую строку файла CSV (заголовок) и заменяя вхождения этих строк (например, apple_val) в текстовый файл.

Как мне это сделать?

2 Solutions collect form web for “Замените все вхождения строки, найденной в файле, используя значения из другого файла”

Изменен вариант alienth (используются массивы):

 #!/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 } 

То же самое с 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 

То, что вы пытаетесь сделать здесь, называется «templating», и ваши собственные шаблоны часто встречаются с неожиданными выбоинами 🙂

Вот сценарий оболочки, который будет делать то, что вы просите, но это не очень и, вероятно, довольно хрупко. Я настоятельно рекомендую взглянуть на более надежное решение для шаблонов.

 #!/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 

Результат вывода, учитывая ввод, указанный вами в вопросе:

 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. 
  • Как я могу сортировать список с уровнем major.minor.patch и иногда rc правильно?
  • Как конвертировать uA / mA в uA в каждой строке csv-файла с помощью c-оболочки?
  • Как обновить i3 блоки при переключении макетов?
  • Как я могу «лениво» читать вывод из xrandr?
  • Как избежать ряда подстановочных знаков в сценарии оболочки unix?
  • Как выйти из цикла bash с клавиатуры?
  • Как ssh на нескольких ipaddress и получить вывод и ошибку на локальной машине * nix?
  • ожидать сценария для получения вывода для нескольких серверов
  • Сценарий для поиска среды рабочего стола по умолчанию?
  • BASH и поведение возврата каретки
  • может ли что-то помимо shebang установить переводчика?
  • Linux и Unix - лучшая ОС в мире.