Как вставить текст в качестве альтернативы из двух файлов с общим шаблоном

У меня есть два файла …

Первый вход в файл …

1 How many steps are in programming? A.5 B.4 C.3 D.9 Ans. 2 How many stairs in room? A.6 B.10 C.15 D.23 Ans. 

Ввод второго файла …

 1. Who is outside of the room ? A.john B.Mary C.Scot D.Fery Ans. 2. Which day is today ? A.Mon B.Wed C.Friday D.Sunday Ans. 

Мне нужен выход вроде …

 1 How many steps are in programming? A.5 B.4 C.3 D.9 Ans. 1. Who is outside of the room ? A.john B.Mary C.Scot D.Fery Ans. 2 How many stairs in room? A.6 B.10 C.15 D.23 Ans. 2. Which day is today ? A.Mon B.Wed C.Friday D.Sunday Ans. 

Я использую команду …

 sed -e '/Ans./{r file2' -e:n -e 'n;bn' -e \} file1 

Но второй o / p из 2 отменяется

 1 How many steps are in programming? A.5 B.4 C.3 D.9 Ans. 1. Who is outside of the room ? A.john B.Mary C.Scot D.Fery Ans. **2. Which day is today ?** A.Mon B.Wed C.Friday D.Sunday Ans. **2 How many stairs in room?** A.6 B.10 C.15 D.23 

Вы можете получить довольно близко, используя awk в режиме абзаца, с getline (он не совсем сохраняет разделители записей – вы можете лучше работать с GNU awk, используя переменную RT ):

 $ awk 'BEGIN{RS=""; ORS="\n\n"} {print; if( (getline < "second") > -1) print}' first 1 How many steps are in programming? A.5 B.4 C.3 D.9 Ans. 1. Who is outside of the room ? A.john B.Mary C.Scot D.Fery Ans. 2 How many stairs in room? A.6 B.10 C.15 D.23 Ans. 2. Which day is today ? A.Mon B.Wed C.Friday D.Sunday Ans. 

Вы можете достичь этого с помощью awk

 awk -v RS='' ' FNR == NR { block[NR] = $0; next } { print block[FNR] "\n\n" $0 "\n" } ' file1 file2 

Блоки разделяются пустыми строками ( RS='' ). Первая строка ( FNR == NR ) хранит блоки file1 в массиве block . Для каждого блока file2 вторая строка печатает соответствующий блок в file1 затем блок в file2 .

Заметки:

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

Если в каждом файле есть разное количество блоков, это (по общему признанию, хакерское) решение с использованием инструментов bash и GNU sed и paste :

 paste -z -d '\n' <(sed -z 's/\n\n/\n\x00/g' file1) <(sed -z 's/\n\n/\n\n\x00/g' file2) 

Команды sed добавляют нулевой байт к разделителям блоков (пустые строки). paste использует этот нулевой байт в качестве разделителя и печатает каждый блок по очереди, разделяя их на новую строку.

Вот сценарий и вывод, чтобы проиллюстрировать использование стандартной пасты утилиты для этого. Сначала простой случай вставки строк поочередно из двух отдельных файлов. Тогда все, что нам нужно сделать, это сделать абзац, ввод строки в одну строку и использовать метод paste. Сборка строк в группе в «суперлинию» выполняется с помощью короткого скрипта perl, который преобразует каждую строку, заменяя новую строку другим символом, в данном случае «@». Затем мы вставляем, а затем разделим суперлинии обратно на абзацы. Это полезно, потому что большинство команд * nix работают на линейном уровне. На самом деле, достаточно полезно, что в нашем магазине у нас есть утилита «масули», чтобы сделать такие суперлинии.

Файлы данных меньше в интересах сохранения визуального пространства.

 #!/usr/bin/env bash # @(#) s1 Demonstrate modular approach to multi-line data, perl, paste. # Utility functions: print-as-echo, print-line-with-visual-space, debug. # export PATH="/usr/local/bin:/usr/bin:/bin" LC_ALL=C ; LANG=C ; export LC_ALL LANG pe() { for _i;do printf "%s" "$_i";done; printf "\n"; } pl() { pe;pe "-----" ;pe "$*"; } em() { pe "$*" >&2 ; } db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; } db() { : ; } C=$HOME/bin/context && [ -f $C ] && $C paste perl pl " Input data file data[12]:" head data[12] pl " Results, proof of concept:" paste -d'\n' data[12] pl " Input data files data[34]:" head data[34] pl " Results, collect, paste, separate:" paste -d'\n' <( perl -00 -wp -e 's/\n/@/g;s/@@/=\n/' data3 ) \ <( perl -00 -wp -e 's/\n/@/g;s/@@/=\n/' data4 ) | tee f1 | perl -000 -wp -e 's/@/\n/g;s/=/\n\n/g;s/\n\n\n/\n\n/g' exit 0 

производство:

 $ ./s1 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64 Distribution : Debian 8.9 (jessie) bash GNU bash 4.3.30 paste (GNU coreutils) 8.23 perl 5.20.2 ----- Input data file data[12]: ==> data1 <== 1.1 1.2 ==> data2 <== 2.1 2.2 ----- Results, proof of concept: 1.1 2.1 1.2 2.2 ----- Input data files data[34]: ==> data3 <== 3.1a 3.1b 3.2a 3.2b ==> data4 <== 4.1a 4.1b 4.2a 4.2b ----- Results, collect, paste, separate: 3.1a 3.1b 4.1a 4.1b 3.2a 3.2b 4.2a 4.2b 

С наилучшими пожеланиями … ура, drl