Moje umiejętności Perl są dość prymitywne i staram się konwertować daty w pliku danych załadowanego w zmiennej skalarnej do czterocyfrowego roku przy użyciu regularnej substytucji ekspresyjnej (między innymi).

Mam następujące czynności, aby dodać 20 do przez wszystkie lata.

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

Jednak daty obejmują te przed 2000 r.

Podczas poszukiwania rozwiązania biegnąłem przez opcję / e, która stwierdziła, że ocenia wymianę jako kod PERL. Jednak nie uważam, że wymieniono w całej dokumentacji, którą biegnąłem i nie jestem pewien, co będzie składnia.

Czy istnieje sposób na ocenę meczu i wyjścia 3 USD 20, jeśli 3 USD jest mniejsze niż 50, aby zrobić 2000 i 19, jeśli nie, aby zrobić 1997? Wybrałem 50, ponieważ wydawało się być bezpiecznym środkiem.

Do celów ilustracyjnych, choć wiem, że jest to nieprawidłowe:

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

Czy / e jest nawet odpowiedni w tym przypadku?

Przykłady linii wyodrębnione z ogromnego pliku tekstowego.

D04/07/97
D04/14/98
D10/06/99
D10/13/05
D03/04/10
D12/09/10
D01/20/11
D12/22/11
1
tanker 21 luty 2019, 18:58

2 odpowiedzi

Najlepsza odpowiedź

Podczas korzystania z /e wyrażenie wymiany musi być ważnym wyrażeniem PERL (tj. Co możesz umieścić podążanie za $x =).

Możesz użyć operatora warunkowego (?:), aby ocenić wyrażenie inaczej oparty na stanie:

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

Należy zauważyć, że wymiana ogranicznika może sprawić, że wszystko jest znacznie bardziejczyni, gdy zaangażowany jest wiele /.

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

Używałbym Czas :: Szt., aby to zrobić. Użyj metody klasy strptime(), aby przeanalizować datę do obiektu, a następnie strftime(), aby go sformatować.

#!/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

Wynik:

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

Roztwór REGEX może być uproszczony przez a) Wybór innego ogranicznika i b) za pomocą operatora Terrary. Jeśli używasz /e, tekst wymiany musi być odpowiednio ważny PERL.

while (<DATA>) {
  chomp;

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

  say;
}

Aktualizacja: Jest jedna (ewentualnie ważna) różnica między dwoma rozwiązaniami - odcięcia między wiekami 20 a 21., konwersją z dwucyfrowych lat do czterocyfrowych. Rozwiązanie REGEX wykorzystuje 50 (jak wspomniano w pierwotnym pytaniu). Czas :: Rozwiązanie szt. Wykorzystuje 69 - a ten limit jest trudny, więc nie ma sposobu na zmianę. Dla danych w pierwotnym pytaniu, to nie ma znaczenia. Ale może mieć znaczenie, jeśli masz dane z rokiem od 1950 do 1969 roku.

1
Dave Cross 22 luty 2019, 05:25