Как я могу условно заменить строку одним словом, используя Perl? - PullRequest
4 голосов
/ 08 февраля 2010

Я хочу заменить строки, оканчивающиеся на «ДА», на «ДА» и заменить строки, оканчивающиеся на «НЕТ», на «НЕТ». Я должен подать заявку на большой файл.

Введите:

 max. C    13       0.457   0.32   YES
 max. Y    13       0.232   0.33   NO
 max. S     1       0.315   0.87   NO  

Выход:

YES
NO
NO

Ответы [ 6 ]

3 голосов
/ 08 февраля 2010

Хотя ответ Павла верен, я хотел бы отметить, что был другой способ взглянуть на вашу проблему.Ваш вопрос гласит, что строка заканчивается «ДА» или «НЕТ».Поэтому вы могли бы также разделить строку и напечатать последний элемент, если он соответствует «YES» или «NO»:

perl -lape'$_=$F[-1] if $F[-1]=~m/^(?:YES|NO)$/'

В вашем примере все строки заканчиваются на YES или NO.Если это действительно так для всех строк вашего ввода, это можно упростить до:

perl -lape'$_=$F[-1]'

Краткое объяснение используемых флагов командной строки Perl (вы также можете прочитать это в perldoc perlrun)):

  • -l используется для автоматического сжатия строк ввода и добавления «\ n» при печати. ​​
  • -a автоматически разбивает строку ввода на пустом месте в @Fмассив, когда используется вместе с "-n" или "-p".
  • -p создает цикл, который проходит по строкам указанного входного файла / файлов и выполняет "печать" в конце после вашеговыполняется код.
  • -e это, конечно, флаг для выдачи кода в командной строке

Так что в основном флаги командной строки выполняют большую часть работы.Единственное, что мне нужно сделать, это присвоить $ F [-1] (последний элемент строки) в $ _, что будет напечатано благодаря «-p».

Моя цель былане играть в Perl Golf и показать вам более короткий способ ответить на ваш вопрос, вместо этого я пытаюсь указать, что простое размышление о проблеме с несколько иной точки зрения может показать вам разные способы ее решения, которые могут быть лучше /более элегантныйПоэтому, пожалуйста, не сосредотачивайтесь на том, какое решение короче, вместо этого подумайте о том, как разные люди атаковали даже эту простую проблему с разных сторон и как вы можете сделать то же самое.

Еще один момент, вы написали: «Я хочузаменить строки ".Если вы подразумевали замену в самом входном файле, то флаг командной строки "-i" (замена на месте) - ваш друг:

perl -lapi.bak -e'$_=$F[-1]'
2 голосов
/ 08 февраля 2010

Соответствие в контексте списка возвращает захваченные подстроки:

#!/usr/bin/perl

use strict; use warnings;

while ( <DATA> ) {
    if (my ($resp) = /(YES|NO)\s+\z/) {
        print "$resp\n";
    }
}

__DATA__
 max. C    13       0.457   0.32   YES
 max. Y    13       0.232   0.33   NO
 max. S     1       0.315   0.87   NO

И, если вы просто хотите захватить 'Y' или 'N', есть два варианта. Один из них - использовать два буфера захвата и использовать grep, чтобы отфильтровать подстроку, которая не совпадает:

if (my ($resp) = grep defined, /(?:(Y)ES)|(?:(N)O)\s+\z/ ) {
    print "$resp\n";
}

или, что еще лучше, используйте именованный буфер захвата:

if ( /(?: (?<resp>Y) ES) | (?: (?<resp>N) O) \s+\z/x ) {
    print "$+{resp}\n";
}

Выход:

Y
N
N
1 голос
/ 02 марта 2010

Вы также можете использовать следующий код,

use strict;
use warnings;
my $var;
open (FH,"<file") or die "$! can't open";
while($var=<FH>)
{
     chomp($var);
     $var=~s/.*(YES|NO)$/$1/;
     print "$var\n";
}

В этом коде я использовал функцию chomp. Эта функция используется для удаления "\ n". После этого я проверил, конец строки содержит «ДА» или «НЕТ»

1 голос
/ 08 февраля 2010

Это зависит от вас, если вам это нужно.

awk '{print $NF}' file_name
1 голос
/ 08 февраля 2010
perl -p -e 's/.*(YES|NO)\s*$/$1/;' 

Если вы хотите, чтобы Y и N вместо YES и NO, измените его на

s/.*(Y|N)[ESO]+$/$1/;

Чтобы узнать больше о регулярных выражениях perl, подстановках и т. Д., Посмотрите «perldoc perlre» в командной строке вашей системы, где установлен perl

0 голосов
/ 03 апреля 2011

Многие из опубликованных ответов используют подстановку s///, чтобы изменить значение строки. Хотя это работает, его нелегко поддерживать. Так почему бы просто не установить строку на YES или NO после успешного совпадения.

use strict;
use warnings;
use autodie;

my $filename = 'file'

{
  open my $fh, '<', $filename;
  while( my $line = <$fh> ){
     chomp($line);

     if( $line =~ /(YES|NO)$/ ){
       $line = $1;
     }

     print $line, "\n";
  }
  close $fh;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...