Объединение нескольких строк в одну строку

У меня есть этот вариант использования XML-файла с входом как

Input:
<abc a="1">
   <val>0.25</val>
</abc> 
<abc a="2">
    <val>0.25</val>
</abc> 
<abc a="3">
   <val>0.35</val>
</abc> 
 ...

Output:
<abc a="1"><val>0.25</val></abc> 
<abc a="2"><val>0.25</val></abc>
<abc a="3"><val>0.35</val></abc>

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

9
задан kal 17 March 2010 в 18:36
поделиться

11 ответов

В vim вы можете сделать это с помощью

:g/<abc/ .,/<\/abc/ join!

Обычно: join добавит пробел в конце каждой строки перед объединением, но ! подавляет это.

В общем, я бы рекомендовал использовать подходящую библиотеку синтаксического анализа XML на таком языке, как Python, Ruby или Perl, для управления XML-файлами (я рекомендую Python + ElementTree), но в этом случае это достаточно просто, чтобы обойтись без регулярного выражения. решение.

4
ответ дан 3 November 2019 в 00:00
поделиться

Вы можете сделать это:

perl -e '$i=1; while(<>){chomp;$s.=$_;if($i%3==0){$s=~s{>\s+<}{><};print "$s\n";$s="";}$i++;}' file
0
ответ дан 3 November 2019 в 00:00
поделиться

Bash:

while read s; do echo -n $s; read s; echo -n $s; read s; echo $s; done < file.xml
1
ответ дан 3 November 2019 в 00:00
поделиться

Вы можете записать макрос. По сути, я бы начал с курсора в начале первой строки. Нажмите «qa» (записывает макрос в регистр). Нажмите Shift-V, чтобы перейти в линейный визуальный режим. Затем найдите конечный тег '// abc'. Затем нажмите shift-J, чтобы соединить линии. Затем вам нужно будет переместить курсор к следующему тегу, возможно, с помощью 'j ^', и нажать 'q', чтобы остановить запись. Затем вы можете перезапустить запись с помощью '@a' или указать 10000 @ a, если хотите. Если теги разные или расположены не сразу друг за другом, вам просто нужно изменить способ нахождения открывающих и закрывающих тегов для поиска или чего-то в этом роде.

1
ответ дан 3 November 2019 в 00:00
поделиться

неэлегантная однострочная программа perl, которая должна сделать этот трюк, хотя и не особенно быстро.

cat file | perl -e '
    $x=0;
    while(<>){
        s/^\s*(\S*(?:\s+\S+)*)\s*$/$1/g;
        print;
        $x++;
    if($x==3){
        print"\n";
        $x=0;
    }
}' > output
0
ответ дан 3 November 2019 в 00:00
поделиться
tr "\n" " "<myfile|sed 's|<\/abc>|<\/abc>\n|g;s/[ \t]*<abc/<abc/g;s/>[ \t]*</></g'
0
ответ дан 3 November 2019 в 00:00
поделиться

В Vim:

  • позиция в первой строке
  • qq : начать запись макроса
  • gJgJ : присоединяется к следующим двум строк без пробелов
  • j : перейти вниз
  • q : остановить запись
  • N @ q : N = количество строк (фактически около 1/3 всех строк, поскольку они сжато на ходу)
4
ответ дан 3 November 2019 в 00:00
поделиться
$ awk '
    /<abc/ && NR > 1 {print ""}
    {gsub(" +"," "); printf "%s",$0}
' file
<abc a="1"> <val>0.25</val></abc>
<abc a="2"> <val>0.25</val></abc>
<abc a="3"> <val>0.35</val></abc>
1
ответ дан 3 November 2019 в 00:00
поделиться
sed '/<abc/,/<\/abc>/{:a;N;s/\n//g;s|<\/abc>|<\/abc>\n|g;H;ta}'  file
0
ответ дан 3 November 2019 в 00:00
поделиться

Это должно работать в режиме ex:

:% s / \ (^ \) ^ M ^ \ (. * \) ^ M ^ \ (^ <\ / abc> \). * ^ M / \ 1 \ 2 \ 3 ^ M / g

У меня должны быть лишние пробелы (или табуляция между значениями), но вы можете удалить их в зависимости от того, что это (\ t или \ \ \ \ ).

То, что вы ищете / заменяете, это (шаблон1) [ввод] (шаблон2) [ввод] (шаблон3) [ввод] и заменяет его на (шаблон1) (шаблон2) (шаблон3) [ввод]

^ M выполняется с помощью ctrl + v CTRL + m

0
ответ дан 3 November 2019 в 00:00
поделиться
sed '/^<abc/{N;N;s/\n\| //g}'

# remove \n or "space" 
# Result

<abca="1"><val>0.25</val></abc>
<abca="2"><val>0.25</val></abc>
<abca="3"><val>0.35</val></abc>
1
ответ дан 3 November 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: