Sed для редактирования заголовка с содержимым другого файла

Я пытаюсь заменить существующий заголовок в файле на основе содержимого другого файла.

File1 – names.in:

name1 name2 name3 name4 name5 

File2- Datafile.tsv:

 chr begin end genes genes genes genes genes 

File2 содержит больше строк, но я хочу заменить каждое вхождение genes строкой в ​​первой строке последовательными записями из file1 , чтобы заголовок стал:

 chr begin end name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected 

Я попробовал следующий скрипт:

 genenames=$1 sed -i -e "1s/\tgenes/\t$genenames\.Corrected/g" Datafile.tsv 

Но когда я запускаю его так:

 ./sed.sh names.in 

Я получаю вывод как:

 chr begin end .in.Corrected .in.Corrected .in.Corrected .in.Corrected .in.Corrected 

Я могу понять, что сценарий не читается со входа. Пожалуйста, предложите подходящее решение.

3 Solutions collect form web for “Sed для редактирования заголовка с содержимым другого файла”

пытаться

 for x in $(<names.in) do sed -i -s "s/ genes/ ${x}.Corrected/" Datafile.tsv done cat Datafile.tsv chr begin end name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected 
  • не используйте флаг /g который будет применяться ко всем вхождениям (вы хотите заменить один за другим)
  • замените мой ' ' на '\t'

  • $names.in будет расширяться до значения переменной имен (concatenate to .in), это, вероятно, будет расширяться до .in

  • $(< name.in ) читать файл name.in, перед выполнением команды и заменять содержимым файла (конец строки превращается в белый)

более полная оболочка

 cat "$1" | while read x do sed -i -s "s/ genes/ ${x}.Corrected/" "$2" done 

называется

  myscript.sh names.in Datafile.tsv 

Если я правильно понял, вам нужно прочитать имена из file1 и заменить каждое вхождение genes строки последовательными записями из файла1, но только в первой строке файла2. Если это так, вы можете сделать это (предполагая, что у вас никогда не будет строки с genes в качестве подстроки, например, mygenes ):

 while read name do sed -i "1s/genes/$name.Corrected/" file2 done < file1 

Кроме того, вы можете просто объединить содержимое файла1 и заменить все за один раз:

 names=$(perl -pe 's/\n/.Corrected /' file1) sed -i "1s/genes .*/$names/" file2 

Ничто не сравнится с циклом while read во время обработки текста, но на всякий случай вы хотите обработать свой файл datafile.tsv только один раз :

 sed 's|\(.*\)|1s/genes/\1.Corrected/|' names.in | sed -f - datafile.tsv 

Первый sed превращает names.in в sed-скрипт :

 1s/genes/name1.Corrected/ 1s/genes/name2.Corrected/ 1s/genes/name3.Corrected/ 1s/genes/name4.Corrected/ 1s/genes/name5.Corrected/ 

который затем выполняется вторым sed .
Если все столбцы ваших генов являются последовательными (например, в вашем примере ввода), вы также можете запустить:

 tr \\n \\t <names.in | \ sed -E 's|\t|.Corrected&|g;s|(.*).$|1s/genes.*genes/\1/|' | \ sed -f - datafile.tsv 

который аналогичен первому, поскольку последний sed выполняет следующий сценарий sed :

 1s/genes.*genes/name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected/ 

Обратите внимание, что они не будут редактировать ваш файл на месте. Для этого либо используйте sed с -i (если поддерживается), либо перенаправляйте > вывод, например, в newfile тогда mv newfile datafile.tsv

Linux и Unix - лучшая ОС в мире.