2012-01-05 32 views
5

Tôi muốn sắp xếp lại dấu thời gian bằng regex Perl với mã ít nhất có thể. Định dạng ban đầu của tem thời gian như sau:Sắp xếp lại dấu thời gian bằng regex Perl

2011/12/29 20:19:45 

Tất cả tôi cần làm là chuyển đổi nó để năm ở phía trước thay vì đưa ra sau khi tháng/ngày như sau:

12/29/2011 20:19:45 

Tôi đã có thể đạt được điều này với 3 dòng mã dưới đây. Tôi chỉ tự hỏi nếu có một cách để làm điều này với mã ít hơn. Đặc biệt, tôi đã cố gắng loại bỏ $ 1 vào một biến trung gian và chỉ định $ 1 từ lần thay thế đầu tiên trực tiếp trong regex cho lần thay thế thứ hai, nhưng điều này dẫn đến lỗi: "Sử dụng giá trị uninitialized $ 1 trong nối (.) hoặc chuỗi. "

Nếu dòng thứ hai không thể thoát khỏi, thì có vẻ như điều này cũng không thể được chuyển xuống một dòng?

#my $ts = '2011/12/29 20:19:45'; #input to a subroutine 

$ts =~ s/^(\d{4})\///; 
my $year = $1; 
$ts =~ s/ /\/$year /; 
+0

Nếu bạn định sửa đổi câu hỏi này, vui lòng nói lý do. Đó là cách SO, và nếu bạn là ai đó từ comp.lang.perl.misc mà tôi đã xúc phạm, tôi xin lỗi, nhưng chúng tôi có một nền văn hóa khác ở đây, và nếu bạn không thích nó, hãy quay lại clpm. Hay bạn không thấy sự trớ trêu của Perl "Có nhiều hơn một cách để làm điều đó" nhưng clpm "Chỉ có một cách để usenet" –

+0

+1 trên bình luận của George. Xin vui lòng không down-mod mà không có một lời giải thích. Đó không phải là hữu ích cho bất cứ ai. – AWT

Trả lời

5

Dưới đây là bạn đi:

$ts =~ s|^(\d{4})/(\d{2})/(\d{2})(.+)$|$2/$3/$1$4|; 

Xin lưu ý rằng các biểu thức trên hy vọng timestamps có chính xác 2 chữ số trong nhiều tháng và ngày và 4 chữ số trong nhiều năm. Nhưng bạn có thể làm cho nó thậm chí ngắn hơn nhưng đáng tin cậy hơn:

$ts =~ s|^(\d+)/(\d+)/(\d+)(.+)$|$2/$3/$1$4|; 

Điều này sẽ xử lý dấu thời gian như 1/12/98 12:34:56 đúng cách.

+0

Cảm ơn câu trả lời mở rộng của bạn, bao gồm lời giải thích và cải thiện trên "tăm xỉa răng" của tôi –

+0

Bất cứ lúc nào. BTW, bạn có thể làm cho regex thậm chí ngắn hơn bằng cách kết hợp ngày và tháng với nhau: 's |^(\ d +)/(\ d +/\ d +) (. +) $ | $ 2/$ 1 $ 3 |' :) –

+0

Cảm ơn và xin vui lòng xem xét up-modding câu hỏi chính nó nếu bạn tìm thấy nó thú vị. Rõ ràng một số troll từ comp.lang.perl.misc sẽ down-mod mỗi câu hỏi Perl tôi yêu cầu ở đây. –

1

Sử dụng Trở lại Tài liệu tham khảo bạn có thể nhận được định dạng mong muốn -

[jaypal:~/Temp] echo "2011/12/29 20:19:45" | 
perl -pe '[email protected]([0-9]{4})/([0-9]{2})/([0-9]{2})@$3/$1/[email protected]' 
29/2011/12 20:19:45 
+2

'\ 3' vv được viết tốt hơn là' $ 3'. – TLP

+1

True ... Tôi không thực sự biết 'perl' chỉ sử dụng khả năng' sed' của nó. Sẽ cập nhật câu trả lời vì có vẻ tốt hơn và cảm ơn phản hồi. :) –

+0

Bạn được chào đón. – TLP

0

Để biết thêm thao tác chung timestamp bạn có thể muốn bay qua strptime/strftime. Trong trường hợp này, nó chỉ là sắp xếp lại trường, nhưng đối với các trường hợp phức tạp hơn như chuyển số tháng thành tên, thì yêu cầu strftime.

my @t = strptime "2011/12/29 20:19:45", "%Y/%m/%d %H:%M:%S"; 

say strftime "%d/%m/%Y %H:%M:%S", @t; # 29/12/2011 20:19:45 
say strftime "%d %b %Y, %H:%M:%S", @t; # 29 December 2011, 20:19:45 
Các vấn đề liên quan