Как в Perl я могу соединить строку ввода со следующей, только если первая заканчивается двоеточием?

Мои строки:

ABC: XYZ
XYZ ABC: XYZ
XYZ:
ABC
XYZ
ABC:
AAB
CCD

Я хочу соединить строки, заканчивающиеся двоеточием, со следующей строкой:

ABC: XYZ
XYZ ABC: XYZ
XYZ: ABC
XYZ
ABC: AAB
CCD

person user935420    schedule 05.11.2011    source источник
comment
@Sinan Ты прав, но, черт возьми, это все плохие ответы.   -  person tchrist    schedule 05.11.2011
comment
@tchrist Если, как я подозреваю, это домашнее задание или вопросы на собеседовании, худшие ответы могут быть лучше ;-)   -  person Sinan Ünür    schedule 05.11.2011
comment
@sinan Наглость детей, просящих других людей сделать за них домашнюю работу, ошеломляет меня. Это было основанием для исключения, когда я учился в университете, и возможности для апелляции не было. Ты сделал свою работу, и точка. Все остальное обман.   -  person tchrist    schedule 05.11.2011


Ответы (5)


Если содержимое помещается в память, загрузите его в одну переменную и сделайте следующее:

$text =~ s/:\n/: /g
person Marcelo Cantos    schedule 05.11.2011
comment
Даже если содержимое может поместиться в памяти, чавканье является неправильным ответом почти в 99,99% случаев. - person Sinan Ünür; 05.11.2011
comment
99,99% случаев? Лично я бы просто делал все, что требует меньшего набора текста. Это неправильно? - person Literat; 05.11.2011
comment
@DanDman Ложная лень не является добродетелью. Пишите алгоритмы, которые масштабируются, а не взрываются. - person tchrist; 05.11.2011
comment
@tchrist tchrist -- Конфуций Perl. - person TLP; 05.11.2011

Если вы просто хотите исправить файл, используйте эту командную строку:

% perl -i.orig -pe 'chomp if /:$/' yourfile

Если вы находитесь в цикле ввода и хотите обнять записи, заканчивающиеся двоеточием, выполните:

while (<>) {
    chomp;
    if (/:$/ && !eof) {
         $_ .= <>;
         redo unless eof;
    }
    # now you have your cuddled line(s), proceed as before
    ...
}

Это предполагает, что последняя строка вашего файла не является строкой продолжения.

person tchrist    schedule 05.11.2011
comment
Мощное большое предположение, поскольку оно переходит в бесконечный цикл, если последняя строка является продолжением! Хотя нравится однострочный. - person Bill Ruppert; 05.11.2011
comment
@Bill Вот почему я упомянул предположение. Об этом позаботится большая доза unless eof, но на телетелефоне она бесполезна. - person tchrist; 05.11.2011
comment
Просто нужно повторить, если только eof; - person Bill Ruppert; 05.11.2011
comment
разве случай eof не покрывается в то время как? - person Bill Ruppert; 06.11.2011
comment
Вместо всей этой сложности, как что-то простое: (а) заменить двоеточие-новую строку на двоеточие-пробел; (б) печать. - person FMc; 06.11.2011
comment
@Bill: Нет, while не распространяется на случай eof. Рассмотрим последнюю строку файла, как всегда. - person tchrist; 06.11.2011

Моя попытка более эстетичной версии.

while (<DATA>) {
  chomp;
  print $_;
  print /:$/ ? " " : "\n";
}

Старая, неприятная попытка. Этот ответ сохраняет только текущую строку в памяти, он не требует глотания ввода или создания всего вывода в памяти. Он также правильно обрабатывает пустые данные, не печатает, если нет ввода.

#!/usr/bin/env perl

use strict;
use warnings;

my $text;
while( my $line = <DATA> ) {
  if ($line =~ /:\s*\n/ && defined $text) {
      print $text;
      undef $text;
  }
  $line =~ s/:\s*\n/: /g;
  $text .= $line;
}
print $text if defined $text;

__DATA__
ABC: XYZ
XYZ ABC: XYZ
XYZ:
ABC
XYZ
ABC:
AAB
CCD
person Bill Ruppert    schedule 05.11.2011
comment
У вас есть одно и то же регулярное выражение в двух местах. Это кажется очень сложным. - person tchrist; 05.11.2011
comment
Стремление к правильности и минимальной памяти, а не к простоте. - person Bill Ruppert; 05.11.2011
comment
Простота приносит ясность. В алгоритмах, как и в доказательствах, чем проще и чище, тем эстетичнее. Почему у вас две переменные? Почему для этого всегда требуется более одной переменной-аккумулятора? - person tchrist; 05.11.2011
comment
Я начал с кода, скопированного снизу и внесшего минимальные изменения. Мне нужен созданный текст, ожидающий печати, и входящая строка, которая может быть добавлена ​​к текущей строке вывода или использована для запуска новой строки вывода. Я лениво использовал статус undef $text в качестве переменной состояния. - person Bill Ruppert; 05.11.2011

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

#!/usr/bin/env perl

use strict;
use warnings;

my $text;
while( my $line = <DATA> ) {
    if ($line =~ s/ : \s+ \z /: /x) {
        $text .= $line;
    }
    else {
        print $text if is_nonempty_string($text);
        print $line;
        $text = '';
    }
}

print $text, "\n" if is_nonempty_string($text);

sub is_nonempty_string { defined($_[0]) and length($_[0]) }

__DATA__
ABC: XYZ
XYZ ABC: XYZ
XYZ:
ABC
XYZ
ABC:
AAB
CCD:
person Joel Berger    schedule 05.11.2011
comment
Выполняет печать на пустом вводе, сохраняет весь вывод в памяти. - person Bill Ruppert; 05.11.2011
comment
Я попытался улучшить исходное решение, не меняя его сути. Смело откатывайте изменения. - person Sinan Ünür; 05.11.2011
comment
хорошо, я думаю, что я собирался немного быстро этим утром. Спасибо Синан. Кажется, что эта задача должна быть проще. - person Joel Berger; 05.11.2011
comment
Хотя, честно говоря, пустой ввод меня не беспокоит. Похоже, это единичный случай, поэтому давайте предположим, что он используется для чего-то. Не говоря уже о том, что отпечаток предназначался для демонстрации, а не для конечного использования. Если ОП хочет постоянного исправления, пусть попробуют, может показаться, что крайних случаев предостаточно. - person Joel Berger; 06.11.2011

person    schedule
comment
Эти вопросы плохо сформулированы, так как невозможно определить, хотят ли они, чтобы тривиальная программа просто соединяла строки продолжения в качестве фильтра или файлового менеджера, или это на самом деле вопрос о том, как изменить существующий входной цикл для учета указанного продолжения. - person tchrist; 05.11.2011