Самый быстрый способ прочитать строки из файла1 и заменить тег строки в файле2

Есть два файла file1 и file2. Их содержание:

файл1 - ввод

Line1
Line2
Line3
Line4

файл2 - ввод

<head>
<intro> This is an introduction </intro>
 <line> this is a line1 </line>
 </head>
<head>
 <intro> This is another intro </intro>
 <line> this is a line2 </intro>
 </head>
<head>
<intro> This is an introduction </intro>
 <line> this is a line3 </line>
 </head>
<head>
 <intro> This is another intro </intro>
 <line> this is a line4 </intro>
 </head>

Хотите прочитать файл1 и заменить значение тега строки в файле2 на строку1, строку2, строку3, строку4 (см. вывод). Какой самый простой способ (sed, awk, grep, perl, python...) сделать это?

Выход

    <head>
    <intro> This is an introduction </intro>
     <line> Line1 </line>
     </head>
    <head>
     <intro> This is another intro </intro>
     <line> Line2 </intro>
     </head>
    <head>
    <intro> This is an introduction </intro>
     <line> Line3 </line>
     </head>
    <head>
     <intro> This is another intro </intro>
     <line> Line4 </intro>
     </head>

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

Редактировать: На случай, если кто-то захочет добавить/объединить вместо замены, можно легко изменить выражение markline в коде python2 @cdarke, как показано ниже, и использовать.


markline = re.sub(r'</line>$',''+subt+'</line>',markline)


person deepseefan    schedule 16.05.2015    source источник
comment
Является ли </intro> опечаткой в ​​некоторых строках с <line>?   -  person Cyrus    schedule 16.05.2015
comment
попытка обрабатывать XML с помощью bash непродуктивна. Выберите perl, groovy, ruby, python... любой из них поможет вам в долгосрочной перспективе.   -  person Jayan    schedule 16.05.2015


Ответы (2)


Самый простой способ, вероятно, тот, с которым вы знакомы. В Perl и Python (а также в Ruby и Lua) все просто, если вы знаете эти языки. «Легко» субъективно.

(Примеры отредактированы с добавлением пробелов)

Вот версия Python 2:

import re

lines = open('file1').readlines()

with open('file2') as fh:
    for markline in fh:
        if '<line>' in markline:
            subt = lines.pop(0).rstrip()
            markline = re.sub(r'<line>.*</line>', '<line> ' + subt + ' </line>',
                          markline)

        print markline,

Вот версия Perl:

use strict;
use warnings;

open(my $fh1, 'file1') or die "Unable to open file1 for read: $!";

my @lines = <$fh1>;
chomp(@lines);
close($fh1);

open(my $fh2, 'file2') or die "Unable to open file2 for read: $!";

while (<$fh2>) {
    s/<line>.*<\/line>/'<line> ' . shift(@lines) . ' <\/line>'/e;
    print 
}

close($fh2);

Я предположил опечатки во входных данных.

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

person cdarke    schedule 16.05.2015
comment
Оба сценария дают одинаковые результаты, однако с каждой стороны замененной строки LineN нет места, как в выводе, показанном в OP. В скрипте Python соответствующая часть строки кода должна быть '<line> ' + subt + ' </line>', а в скрипте Perl должна быть '<line> ' . shift(@lines) . ' <\/line>'. Я попытался отредактировать его сам, однако добавления 4 пробелов было недостаточно, чтобы разрешить редактирование. - person user3439894; 16.05.2015
comment
@ user3439894: спасибо. Я добавил пробелы в код. - person cdarke; 17.05.2015

С заменой процессов GNU sed и bash:

sed -e '/<line>[^<]*<\/[^>]*>/{R '<(sed 's|.*| <line> & </line>|' file1) -e 'd;}' file2

Выход:

<head>
<intro> This is an introduction </intro>
 <line> Line1 </line>
 </head>
<head>
 <intro> This is another intro </intro>
 <line> Line2 </line>
 </head>
<head>
<intro> This is an introduction </intro>
 <line> Line3 </line>
 </head>
<head>
 <intro> This is another intro </intro>
 <line> Line4 </line>
 </head>
person Cyrus    schedule 16.05.2015