Объединение двух однострочных команд Perl в скрипт

Я пытаюсь объединить следующие два однострочных Perl-кода в один Perl-скрипт, который выполняет оба в строке файла, прежде чем перейти к следующей строке. Обратите внимание, что это не мой собственный исходный код, он был очень продуманно представлен здесь: Добавление пустой строки между несвязанными записями данных

1

perl -pae 'print $/ if (defined $x && $x ne $F[0]); $x = $F[0];' DF-data2pfa.csv >DF-data2pfb.txt

2

perl -pae 'print $/ if (defined $x && $x ne $F[3]); $x = $F[3];' DF-data2pfb.txt >DF-data2pfc.txt

Скрипт делает именно то, что я хочу (сравнивает поле F[0] строки в моем наборе данных с полем F[0] предыдущей строки и добавляет пустую строку между этими записями, если они разные), за исключением того, что я понял, что мне нужно, чтобы он выглядел в F[0] и F[3] в одной строке и сравните их с предыдущей строкой. К моему большому смущению, я пытался просто запускать одну за другой и не осознавал, что это добавляло дополнительную пустую строку каждый раз, когда скрипт встречал пустую строку, добавленную предыдущим скриптом, что неприемлемо для программы, которую я пытаюсь ввести. данные к.

Поэтому я попытался использовать инструмент Deparse для преобразования обоих в формат сценария, а затем использовать оператор elsif для добавления второго к первому. Это стало грязно. Также я не уверен, как добиться функции pae командной строки в скрипте. Я не уверен, что e необходим в сценарии, но кажется, что сначала распечатать каждую строку, а затем разбить ее на массив (с pa) является довольно неотъемлемым компонентом всего этого кода, и я не уверен, как этого добиться здесь.

Вот что я получил:

while (defined($_ = <ARGV>)) {
    our(@F) = split(' ', $_, 0);
$x = $F[0];
$y = $F[3];
if defined $x and $x ne $F[0];
elsif defined $y and $y ne $F[3];
   print $/ 
}
continue {
    die "-p destination: $!\n" unless print $_;
}

Я также готов не использовать модуль deparse, если он здесь не нужен. Спасибо за любую помощь/объяснения, которые вы можете предоставить!


person user1784467    schedule 11.03.2013    source источник


Ответы (2)


Это становится немного многословным для однострочника, но вы можете сделать это:

perl -pae 'print $/ if ((defined $x && $x ne $F[0]) && (defined $y && $y ne $F[3])); $x = $F[0]; $y = $F[3]' DF-data2pfa.csv >DF-data2pfb.txt

или как скрипт

open my $fh, "<", "input_file_name";
open my $out, ">", "output_file_name";
my ($x, $y);
foreach (<$fh>) {
    my @F = split(' ', $_);
    if ( ( defined($x) && $x ne $F[0] ) && (defined($y) && $y ne $F[3]) ) {
        print $OUT $\;
    }
    $x = $F[0];
    $y = $F[3];
    print $OUT $_;
}

Я не уверен, что правильно читаю ваши требования - если вам нужно напечатать дополнительную строку, если $F[0] или $F[3] соответствует предыдущей строке, тогда условное выражение будет таким:

( ( defined($x) && $x ne $F[0] ) || (defined($y) && $y ne $F[3]) )
person RickF    schedule 11.03.2013
comment
Ах да, наверное, я не связно объяснил. Я закончил тем, что изменил однострочник, который вы вставили, с последним перечисленным вами условием. Получилось как я и хотел, большое спасибо. - person user1784467; 12.03.2013

Я не уверен на 100%, что вы делаете, поэтому этот сценарий может быть не совсем тем, что вам нужно, но, надеюсь, он поможет вам начать работу. Он использует прагмы strict и warnings, которые помогут вам предотвратить определенные ошибки.

#!/usr/bin/env perl

use strict;
use warnings;

my ($x, $y, @F);
while ( <> ) {
  @F = split ' ';
  if ( defined $x and $x ne $F[0] ) {
    print $/;
  } elsif ( defined $y and $y ne $F[3] ) {
    print $/;
  }
  $x = $F[0];
  $y = $F[3];
  print;
}

Это неявно использует переменную $_ (while неявно устанавливает ее, split неявно использует ее). Он также показывает, как должны выглядеть ваши условные операторы; если не используется в стиле posfix, условия НЕОБХОДИМЫ круглые скобки. Я оставил в блоке continue, но на практике мне никогда не приходилось его использовать, это, вероятно, остаток deparse и, вероятно, мог бы идти в конце цикла while (и print тоже может неявно использовать $_). Наконец, оператор <> является волшебным оператором открытия/чтения, он будет использовать файлы в ARGV последовательно или при необходимости использовать STDIN.

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

person Joel Berger    schedule 11.03.2013
comment
вы можете либо передать имя файла сценарию perl scriptname.pl file1 file2 ..., либо передать его в cat file1 | perl scriptname. Либо будет работать. - person Joel Berger; 12.03.2013
comment
Это называется «волшебным открытием» свойства «алмазного оператора», если вы хотите погуглить. Также это задокументировано в этом разделе perldoc perlop. - person Joel Berger; 12.03.2013
comment
Гах, я должен был понять. Что ж, теперь я передаю имя файла сценарию, однако, похоже, он просто перепечатывает весь файл, независимо от того, что я указал под комментариями # do something. Есть ли определенное количество отступов, которые мне нужно сделать под операторами if и elsif? - person user1784467; 12.03.2013
comment
Я обновил, чтобы мой код (должен) делать то же самое, что и блок кода RickF. И нет, как и в большинстве C-подобных языков, пробелы не имеют значения для интерпретатора. - person Joel Berger; 12.03.2013