Заменить n-ю строку в файле из другого файла

#bash #sed #text-processing

#bash #sed #обработка текста

Вопрос:

У меня есть несколько файлов в разных подкаталогах, где один подкаталог содержит файл с правильной информацией в 6-й строке, а остальные содержат только фиктивную информацию. Структура каталогов выглядит следующим образом:

 Folder-1
    Subfolder-1
        File-A
   SubfFolder-2
        File-B
    Subfolder-3
        File-B
Folder-2
    ...
Folder-3
...
  

File-A in Subfolder-1 содержит правильный текст в строке 6, который является строкой, которая отличается для каждого Folder . File-B содержит фиктивный текст

 E1 E2 E3 E4 E5 N
  

в строке 6. Этот фиктивный текст также идентичен в каждом Folder . Мне нужно заменить эту фиктивную строку правильной строкой в каждом Folder , чтобы каждая File из Folder них содержала одну и ту же строку в строке 6.

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

 sed -i 's/String1/String2/g' file
  

Грубый набросок, который я представляю, это:

 for i in */;
     do for j in 2 3;
     do sed  6th line in "$i"Subfolder-1/File-A > 6th line in "$i"Subfolder-"$j"/File-B               % Magic needed
done
done
  

Ответ №1:

Sed может печатать определенную строку в файле:

 sed -n '6p' file
# store it to a variable via
replacement=$(sed -n '6p' file)
  

Вместо замены (которая не будет работать хорошо, если ваша 6-я строка соответствует другим строкам в вашем файле), вы можете удалить старую 6-ю строку и вставить новую 6-ю строку перед строкой 7:

 sed -i -e '6d' -e "7i$replacement" file
  

Ответ №2:

Давайте рассмотрим это поэтапно.

Нам понадобится find команда. Чтобы найти все папки:

 find . -name "Folder-*"
  

Пока все хорошо. Теперь, чтобы что-то сделать с каждой папкой:

 find . -name "Folder-*" | while read dname; do
  echo $dname
done
  

Теперь, чтобы извлечь правильную строку из File-A:

 find . -name "Folder-*" | while read dname; do
  echo $dname
  good=`sed -n '6p' $dname/Subfolder-1/File-A`
  echo $good
done
  

Теперь, чтобы найти все файлы-Bs, используя внутренний find , специфичный для папки:

 find . -name "Folder-*" | while read dname; do
  echo $dname
  find $dname -name File-B
done
  

Теперь, чтобы изменить каждый из этих файлов find , выполнив внутреннюю sed команду, заменив каждую шестую строку на «заполнитель»:

 find . -name "Folder-*" | while read dname; do
  echo $dname
  find $dname -name File-B -exec sed -i '' "6s/.*/placeholder/" {} ;
done
  

Теперь, чтобы собрать все это вместе и использовать переменную good :

 find . -name "Folder-*" | while read dname; do
  good=`sed -n '6p' $dname/Subfolder-1/File-A`
  find $dname -name File-B -exec sed -i '' "6s/.*/$good/" {} ;
done