perlfaq4.pod
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· POD 代码 · 共 2,029 行 · 第 1/5 页
POD
2,029 行
a time in epoch seconds for the argument to localtime. use POSIX qw/mktime strftime/; my $week_of_year = strftime "%W", localtime( mktime( 0, 0, 0, 18, 11, 87 ) );The C<Date::Calc> module provides two functions to calculate these. use Date::Calc; my $day_of_year = Day_of_Year( 1987, 12, 18 ); my $week_of_year = Week_of_Year( 1987, 12, 18 );=head2 How do I find the current century or millennium?Use the following simple functions: sub get_century { return int((((localtime(shift || time))[5] + 1999))/100); } sub get_millennium { return 1+int((((localtime(shift || time))[5] + 1899))/1000); }On some systems, the C<POSIX> module's C<strftime()> function has beenextended in a non-standard way to use a C<%C> format, which theysometimes claim is the "century". It isn't, because on most suchsystems, this is only the first two digits of the four-digit year, andthus cannot be used to reliably determine the current century ormillennium.=head2 How can I compare two dates and find the difference?(contributed by brian d foy)You could just store all your dates as a number and then subtract.Life isn't always that simple though. If you want to work withformatted dates, the C<Date::Manip>, C<Date::Calc>, or C<DateTime>modules can help you.=head2 How can I take a string and turn it into epoch seconds?If it's a regular enough string that it always has the same format,you can split it up and pass the parts to C<timelocal> in the standardC<Time::Local> module. Otherwise, you should look into the C<Date::Calc>and C<Date::Manip> modules from CPAN.=head2 How can I find the Julian Day?(contributed by brian d foy and Dave Cross)You can use the C<Time::JulianDay> module available on CPAN. Ensurethat you really want to find a Julian day, though, as many people havedifferent ideas about Julian days. Seehttp://www.hermetic.ch/cal_stud/jdn.htm for instance.You can also try the C<DateTime> module, which can convert a date/timeto a Julian Day. $ perl -MDateTime -le'print DateTime->today->jd' 2453401.5Or the modified Julian Day $ perl -MDateTime -le'print DateTime->today->mjd' 53401Or even the day of the year (which is what some people think of as aJulian day) $ perl -MDateTime -le'print DateTime->today->doy' 31=head2 How do I find yesterday's date?(contributed by brian d foy)Use one of the Date modules. The C<DateTime> module makes it simple, andgive you the same time of day, only the day before. use DateTime; my $yesterday = DateTime->now->subtract( days => 1 ); print "Yesterday was $yesterday\n";You can also use the C<Date::Calc> module using its C<Today_and_Now>function. use Date::Calc qw( Today_and_Now Add_Delta_DHMS ); my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 ); print "@date_time\n";Most people try to use the time rather than the calendar to figure outdates, but that assumes that days are twenty-four hours each. Formost people, there are two days a year when they aren't: the switch toand from summer time throws this off. Let the modules do the work.=head2 Does Perl have a Year 2000 problem? Is Perl Y2K compliant?Short answer: No, Perl does not have a Year 2000 problem. Yes, Perl isY2K compliant (whatever that means). The programmers you've hired touse it, however, probably are not.Long answer: The question belies a true understanding of the issue.Perl is just as Y2K compliant as your pencil--no more, and no less.Can you use your pencil to write a non-Y2K-compliant memo? Of courseyou can. Is that the pencil's fault? Of course it isn't.The date and time functions supplied with Perl (gmtime and localtime)supply adequate information to determine the year well beyond 2000(2038 is when trouble strikes for 32-bit machines). The year returnedby these functions when used in a list context is the year minus 1900.For years between 1910 and 1999 this I<happens> to be a 2-digit decimalnumber. To avoid the year 2000 problem simply do not treat the year asa 2-digit number. It isn't.When gmtime() and localtime() are used in scalar context they returna timestamp string that contains a fully-expanded year. For example,C<$timestamp = gmtime(1005613200)> sets $timestamp to "Tue Nov 13 01:00:002001". There's no year 2000 problem here.That doesn't mean that Perl can't be used to create non-Y2K compliantprograms. It can. But so can your pencil. It's the fault of the user,not the language. At the risk of inflaming the NRA: "Perl doesn'tbreak Y2K, people do." See http://www.perl.org/about/y2k.html fora longer exposition.=head1 Data: Strings=head2 How do I validate input?(contributed by brian d foy)There are many ways to ensure that values are what you expect orwant to accept. Besides the specific examples that we cover in theperlfaq, you can also look at the modules with "Assert" and "Validate"in their names, along with other modules such as C<Regexp::Common>.Some modules have validation for particular types of input, suchas C<Business::ISBN>, C<Business::CreditCard>, C<Email::Valid>,and C<Data::Validate::IP>.=head2 How do I unescape a string?It depends just what you mean by "escape". URL escapes are dealtwith in L<perlfaq9>. Shell escapes with the backslash (C<\>)character are removed with s/\\(.)/$1/g;This won't expand C<"\n"> or C<"\t"> or any other special escapes.=head2 How do I remove consecutive pairs of characters?(contributed by brian d foy)You can use the substitution operator to find pairs of characters (orruns of characters) and replace them with a single instance. In thissubstitution, we find a character in C<(.)>. The memory parenthesesstore the matched character in the back-reference C<\1> and we usethat to require that the same thing immediately follow it. We replacethat part of the string with the character in C<$1>. s/(.)\1/$1/g;We can also use the transliteration operator, C<tr///>. In thisexample, the search list side of our C<tr///> contains nothing, butthe C<c> option complements that so it contains everything. Thereplacement list also contains nothing, so the transliteration isalmost a no-op since it won't do any replacements (or more exactly,replace the character with itself). However, the C<s> option squashesduplicated and consecutive characters in the string so a characterdoes not show up next to itself my $str = 'Haarlem'; # in the Netherlands $str =~ tr///cs; # Now Harlem, like in New York=head2 How do I expand function calls in a string?(contributed by brian d foy)This is documented in L<perlref>, and although it's not the easiestthing to read, it does work. In each of these examples, we call thefunction inside the braces used to dereference a reference. If wehave more than one return value, we can construct and dereference ananonymous array. In this case, we call the function in list context. print "The time values are @{ [localtime] }.\n";If we want to call the function in scalar context, we have to do a bitmore work. We can really have any code we like inside the braces, sowe simply have to end with the scalar reference, although how you dothat is up to you, and you can use code inside the braces. Note thatthe use of parens creates a list context, so we need C<scalar> toforce the scalar context on the function: print "The time is ${\(scalar localtime)}.\n" print "The time is ${ my $x = localtime; \$x }.\n";If your function already returns a reference, you don't need to createthe reference yourself. sub timestamp { my $t = localtime; \$t } print "The time is ${ timestamp() }.\n";The C<Interpolation> module can also do a lot of magic for you. You canspecify a variable name, in this case C<E>, to set up a tied hash thatdoes the interpolation for you. It has several other methods to do thisas well. use Interpolation E => 'eval'; print "The time values are $E{localtime()}.\n";In most cases, it is probably easier to simply use string concatenation,which also forces scalar context. print "The time is " . localtime() . ".\n";=head2 How do I find matching/nesting anything?This isn't something that can be done in one regular expression, nomatter how complicated. To find something between two singlecharacters, a pattern like C</x([^x]*)x/> will get the interveningbits in $1. For multiple ones, then something more likeC</alpha(.*?)omega/> would be needed. But none of these deals withnested patterns. For balanced expressions using C<(>, C<{>, C<[> orC<< < >> as delimiters, use the CPAN module Regexp::Common, or seeL<perlre/(??{ code })>. For other cases, you'll have to write aparser.If you are serious about writing a parser, there are a number ofmodules or oddities that will make your life a lot easier. There arethe CPAN modules C<Parse::RecDescent>, C<Parse::Yapp>, andC<Text::Balanced>; and the C<byacc> program. Starting from perl 5.8the C<Text::Balanced> is part of the standard distribution.One simple destructive, inside-out approach that you might try is topull out the smallest nesting parts one at a time: while (s/BEGIN((?:(?!BEGIN)(?!END).)*)END//gs) { # do something with $1 }A more complicated and sneaky approach is to make Perl's regularexpression engine do it for you. This is courtesy Dean Inada, andrather has the nature of an Obfuscated Perl Contest entry, but itreally does work: # $_ contains the string to parse # BEGIN and END are the opening and closing markers for the # nested text. @( = ('(',''); @) = (')',''); ($re=$_)=~s/((BEGIN)|(END)|.)/$)[!$3]\Q$1\E$([!$2]/gs; @$ = (eval{/$re/},$@!~/unmatched/i); print join("\n",@$[0..$#$]) if( $$[-1] );=head2 How do I reverse a string?Use C<reverse()> in scalar context, as documented inL<perlfunc/reverse>. $reversed = reverse $string;=head2 How do I expand tabs in a string?You can do it yourself: 1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;Or you can just use the C<Text::Tabs> module (part of the standard Perldistribution). use Text::Tabs; @expanded_lines = expand(@lines_with_tabs);=head2 How do I reformat a paragraph?Use C<Text::Wrap> (part of the standard Perl distribution): use Text::Wrap; print wrap("\t", ' ', @paragraphs);The paragraphs you give to C<Text::Wrap> should not contain embeddednewlines. C<Text::Wrap> doesn't justify the lines (flush-right).Or use the CPAN module C<Text::Autoformat>. Formatting files can beeasily done by making a shell alias, like so: alias fmt="perl -i -MText::Autoformat -n0777 \ -e 'print autoformat $_, {all=>1}' $*"See the documentation for C<Text::Autoformat> to appreciate its manycapabilities.=head2 How can I access or change N characters of a string?You can access the first characters of a string with substr().To get the first character, for example, start at position 0and grab the string of length 1. $string = "Just another Perl Hacker"; $first_char = substr( $string, 0, 1 ); # 'J'To change part of a string, you can use the optional fourthargument which is the replacement string. substr( $string, 13, 4, "Perl 5.8.0" );You can also use substr() as an lvalue. substr( $string, 13, 4 ) = "Perl 5.8.0";=head2 How do I change the Nth occurrence of something?You have to keep track of N yourself. For example, let's say you wantto change the fifth occurrence of C<"whoever"> or C<"whomever"> intoC<"whosoever"> or C<"whomsoever">, case insensitively. Theseall assume that $_ contains the string to be altered. $count = 0; s{((whom?)ever)}{ ++$count == 5 # is it the 5th? ? "${2}soever" # yes, swap : $1 # renege and leave it there }ige;In the more general case, you can use the C</g> modifier in a C<while>loop, keeping count of matches. $WANT = 3; $count = 0; $_ = "One fish two fish red fish blue fish"; while (/(\w+)\s+fish\b/gi) { if (++$count == $WANT) { print "The third fish is a $1 one.\n"; } }That prints out: C<"The third fish is a red one."> You can also use arepetition count and repeated pattern like this: /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i;=head2 How can I count the number of occurrences of a substring within a string?There are a number of ways, with varying efficiency. If you want acount of a certain single character (X) within a string, you can use theC<tr///> function like so: $string = "ThisXlineXhasXsomeXx'sXinXit"; $count = ($string =~ tr/X//); print "There are $count X characters in the string";This is fine if you are just looking for a single character. However,if you are trying to count multiple character substrings within alarger string, C<tr///> won't work. What you can do is wrap a while()loop around a global pattern match. For example, let's count negativeintegers: $string = "-9 55 48 -2 23 -76 4 14 -44"; while ($string =~ /-\d+/g) { $count++ } print "There are $count negative numbers in the string";Another version uses a global match in list context, then assigns theresult to a scalar, producing a count of the number of matches. $count = () = $string =~ /-\d+/g;=head2 How do I capitalize all the words on one line?To make the first letter of each word upper case: $line =~ s/\b(\w)/\U$1/g;This has the strange effect of turning "C<don't do it>" into "C<Don'TDo It>". Sometimes you might want this. Other times you might need amore thorough solution (Suggested by brian d foy): $string =~ s/ ( (^\w) #at the beginning of the line | # or (\s\w) #preceded by whitespace ) /\U$1/xg; $string =~ s/([\w']+)/\u\L$1/g;To make the whole line upper case: $line = uc($line);To force each word to be lower case, with the first letter upper case: $line =~ s/(\w+)/\u\L$1/g;You can (and probably should) enable locale awareness of thosecharacters by placing a C<use locale> pragma in your program.See L<perllocale> for endless details on locales.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?