Подстановка регулярных выражений с условной заменой в Perl - PullRequest
0 голосов
/ 21 февраля 2019

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

I 'У нас есть следующее, чтобы добавить 20 ко всем годам.

$data00 =~ s/^D(\d{2})\/(\d{2})\/(\d{2})\n/D$1\/$2\/20$3\n/gm;

Однако даты включают даты до 2000 года.

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

Есть ли способ оценить совпадение $ 3 и вывести 20, если $ 3менее 50, чтобы сделать 2000 и 19, если нет, чтобы сделать 1997?Я выбрал 50, потому что это казалось безопасным средним уровнем.

Для иллюстрации, хотя я знаю, что это неверно:

$data00 =~ s/^D(\d{2})\/(\d{2})\/(\d{2})\n/D$1\/$2\/(if($3<50)20 else 19)$3\n/eg;

Является ли / e даже уместным в этом случае?

Примеры строк, извлеченные из огромного текстового файла.

D04/07/97
D04/14/98
D10/06/99
D10/13/05
D03/04/10
D12/09/10
D01/20/11
D12/22/11

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Я бы использовал Time :: Piece , чтобы сделать это.Используйте метод класса strptime() для анализа даты в объекте, а затем strftime() для ее форматирования.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';
use Time::Piece;

while (<DATA>) {
  chomp;

  my $date = Time::Piece->strptime($_, 'D%m/%d/%y');

  say $date->strftime('D%m/%d/%Y');
}

__DATA__
D04/07/97
D04/14/98
D10/06/99
D10/13/05
D03/04/10
D12/09/10
D01/20/11
D12/22/11

Вывод:

D04/07/1997
D04/14/1998
D10/06/1999
D10/13/2005
D03/04/2010
D12/09/2010
D01/20/2011
D12/22/2011

Решение для регулярных выражений может быть упрощеноа) выбрав другой разделитель и б) используя троичный оператор.Если вы используете /e, то текст замены должен быть синтаксически действительным Perl.

while (<DATA>) {
  chomp;

  s|D(\d{2}/\d{2}/)(\d{2})|"D$1" . ($2 < 50 ? '20' : '19') . $2|e;

  say;
}

Обновление: Существует одно (возможно, важное) различие между двумя решениями - отсечениемежду 20-м и 21-м веками при преобразовании двузначных лет в четырехзначные.Решение регулярных выражений использует 50 (как упомянуто в оригинальном вопросе).В решении Time :: Piece используется 69 - и этот предел жестко закодирован, поэтому его невозможно изменить.Для данных в исходном вопросе это не имеет значения.Но это может иметь значение, если у вас есть данные за год с 1950 по 1969 год.

0 голосов
/ 21 февраля 2019

При использовании /e выражение замены должно быть допустимым выражением Perl (т. Е. То, что вы можете поместить после $x =).

Вы можете использовать условный оператор (?:) для оценкивыражение по-разному в зависимости от условия:

s/^D(\d{2})\/(\d{2})\/(\d{2})\n/ "D$1\/$2\/".( $3 < 50 ? 20 : 19 )."$3\n" /eg

Обратите внимание, что замена разделителя может сделать вещи более читабельными, если задействовано много /.

s{^D(\d{2})/(\d{2})/(\d{2})\n}{ "D$1/$2/".( $3 < 50 ? 20 : 19 )."$3\n" }eg
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...