Заполните пустые строки в текстовом файле каждой строкой другого файла - PullRequest
3 голосов
/ 11 марта 2020

Так что в основном у меня есть текстовый файл с множеством пустых строк. Давайте назовем это time.txt , и часть этого файла выглядит следующим образом:

       1          5   20    
       2          5   12    
       1          6   3    
       2          6   4

       1          10   30    
       2          10   21    
       1          11   27    
       2          12   8
       1          11   34    
       2          12   20

       1          10   30    
       2          10   21  

Теперь у меня есть другой файл с именем location.txt , который содержит столько же строк, сколько пустых строк в time.txt . Это выглядит так:

   110      -7      5.000              66
   110      -7      5.000              99
   110      -7      5.000              60

И то, что я хочу, на самом деле просто: я просто хочу заполнить пустые строки в time.txt каждой строкой в ​​ location.txt , дающий ожидаемые результаты:

   110      -7      5.000              66
       1          5   20    
       2          5   12    
       1          6   3    
       2          6   4
   110      -7      5.000              99
       1          10   30    
       2          10   21    
       1          11   27    
       2          12   8
       1          11   34    
       2          12   20
   110      -7      5.000              60
       1          10   30    
       2          10   21  

Мой способ решить эту проблему - прочитать строку за строкой location.txt , сохранить каждую строку в переменной в пределах l oop, а затем с помощью awk обнаружить пустые строки внутри time.txt и заменить его сохраненной переменной l oop. Мой код выглядит так:

time="time.txt"
location="location.txt"
while read -r lines_locs; do
    awk '!NF{$0=$lines_locs}1' $time
done < "$location"

, но это только выводит time.txt на моем экране без замены. Кроме того, у меня было напечатано слишком много строк по сравнению с ожидаемым количеством строк. Я уверен, что что-то упустил, и я был бы рад, если бы кто-то мог указать на это.

Ответы [ 3 ]

5 голосов
/ 11 марта 2020

Один в awk, используя getline:

$ awk -v file="$location" 'NF==0{if((getline < file)<=0)$0=""}1' "$time"

Объяснено:

$ awk -v file="$location" '    # location file as parameter
NF==0 {                        # NF==0 considers bare space records empty
    if((getline < file)<=0)    # when empty read from another file. if failure
        $0=""                  # reset the record. see comments for discussion
}1' "$time"                    # output

Вывод:

   110      -7      5.000              66
       1          5   20    
       2          5   12    
       1          6   3    
       2          6   4
   110      -7      5.000              99
       1          10   30    
       2          10   21    
       1          11   27    
       2          12   8
       1          11   34    
       2          12   20
   110      -7      5.000              60
       1          10   30    
       2          10   21  

Если в файле location заканчивается записи, скрипт печатает пустые записи. См. Комментарии к соответствующему обсуждению.

3 голосов
/ 11 марта 2020

Если вы в порядке с GNU sed, вы можете использовать

sed -e '/^$/{R '"$location" -e 'd}' "$time"
  • /^$/ совпадения с пустой строкой из $time файла
  • R, команда позволяет вам чтобы прочитать по одной строке за раз из данного файла, $location в этом случае
  • d команда затем удаляет пустую строку
  • , если совпадает пустая строка, но больше строк для чтения нет, тогда пустая строка удаляется

Используйте sed -i, если вы хотите sh, чтобы изменить $time файл на месте

1 голос
/ 11 марта 2020

Предположим, location.txt не настолько массивен, что не помещается в памяти:

$ awk 'NR==FNR{loc[NR]=$0; next} {print (NF ? $0 : loc[++c])}' location.txt time.txt
   110      -7      5.000              66
       1          5   20
       2          5   12
       1          6   3
       2          6   4
   110      -7      5.000              99
       1          10   30
       2          10   21
       1          11   27
       2          12   8
       1          11   34
       2          12   20
   110      -7      5.000              60
       1          10   30
       2          10   21
...