⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perlfaq4.pod

📁 MSYS在windows下模拟了一个类unix的终端
💻 POD
📖 第 1 页 / 共 5 页
字号:
	my $lastpos   = 1;	for my $place (@positions) {	    $template .= "A" . ($place - $lastpos) . " "; 	    $lastpos   = $place;	}	$template .= "A*";	return $template;    }=head2 How do I find the soundex value of a string?Use the standard Text::Soundex module distributed with Perl.Before you do so, you may want to determine whether `soundex' is infact what you think it is.  Knuth's soundex algorithm compresses wordsinto a small space, and so it does not necessarily distinguish betweentwo words which you might want to appear separately.  For example, thelast names `Knuth' and `Kant' are both mapped to the soundex code K530.If Text::Soundex does not do what you are looking for, you might wantto consider the String::Approx module available at CPAN.=head2 How can I expand variables in text strings?Let's assume that you have a string like:    $text = 'this has a $foo in it and a $bar';If those were both global variables, then this wouldsuffice:    $text =~ s/\$(\w+)/${$1}/g;  # no /e neededBut since they are probably lexicals, or at least, they couldbe, you'd have to do this:    $text =~ s/(\$\w+)/$1/eeg;    die if $@;			# needed /ee, not /eIt's probably better in the general case to treat thosevariables as entries in some special hash.  For example:    %user_defs = ( 	foo  => 23,	bar  => 19,    );    $text =~ s/\$(\w+)/$user_defs{$1}/g;See also ``How do I expand function calls in a string?'' in this sectionof the FAQ.=head2 What's wrong with always quoting "$vars"?The problem is that those double-quotes force stringification--coercing numbers and references into strings--even when youdon't want them to be strings.  Think of it this way: double-quoteexpansion is used to produce new strings.  If you already have a string, why do you need more?If you get used to writing odd things like these:    print "$var";   	# BAD    $new = "$old";   	# BAD    somefunc("$var");	# BADYou'll be in trouble.  Those should (in 99.8% of the cases) bethe simpler and more direct:    print $var;    $new = $old;    somefunc($var);Otherwise, besides slowing you down, you're going to break code whenthe thing in the scalar is actually neither a string nor a number, buta reference:    func(\@array);    sub func {	my $aref = shift;	my $oref = "$aref";  # WRONG    }You can also get into subtle problems on those few operations in Perlthat actually do care about the difference between a string and anumber, such as the magical C<++> autoincrement operator or thesyscall() function.Stringification also destroys arrays.      @lines = `command`;    print "@lines";		# WRONG - extra blanks    print @lines;		# right=head2 Why don't my <<HERE documents work?Check for these three things:=over 4=item 1. There must be no space after the << part.=item 2. There (probably) should be a semicolon at the end.=item 3. You can't (easily) have any space in front of the tag.=backIf you want to indent the text in the here document, you can do this:    # all in one    ($VAR = <<HERE_TARGET) =~ s/^\s+//gm;        your text        goes here    HERE_TARGETBut the HERE_TARGET must still be flush against the margin.If you want that indented also, you'll have to quote in the indentation.    ($quote = <<'    FINIS') =~ s/^\s+//gm;            ...we will have peace, when you and all your works have            perished--and the works of your dark master to whom you            would deliver us. You are a liar, Saruman, and a corrupter            of men's hearts.  --Theoden in /usr/src/perl/taint.c        FINIS    $quote =~ s/\s*--/\n--/;A nice general-purpose fixer-upper function for indented here documentsfollows.  It expects to be called with a here document as its argument.It looks to see whether each line begins with a common substring, andif so, strips that substring off.  Otherwise, it takes the amount of leadingwhitespace found on the first line and removes that much off eachsubsequent line.    sub fix {        local $_ = shift;        my ($white, $leader);  # common whitespace and common leading string        if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\1\2?.*\n)+$/) {            ($white, $leader) = ($2, quotemeta($1));        } else {            ($white, $leader) = (/^(\s+)/, '');        }        s/^\s*?$leader(?:$white)?//gm;        return $_;    }This works with leading special strings, dynamically determined:    $remember_the_main = fix<<'    MAIN_INTERPRETER_LOOP';	@@@ int	@@@ runops() {	@@@     SAVEI32(runlevel);	@@@     runlevel++;	@@@     while ( op = (*op->op_ppaddr)() );	@@@     TAINT_NOT;	@@@     return 0;	@@@ }    MAIN_INTERPRETER_LOOPOr with a fixed amount of leading whitespace, with remainingindentation correctly preserved:    $poem = fix<<EVER_ON_AND_ON;       Now far ahead the Road has gone,	  And I must follow, if I can,       Pursuing it with eager feet,	  Until it joins some larger way       Where many paths and errands meet.	  And whither then? I cannot say.		--Bilbo in /usr/src/perl/pp_ctl.c    EVER_ON_AND_ON=head1 Data: Arrays=head2 What is the difference between a list and an array?An array has a changeable length.  A list does not.  An array is somethingyou can push or pop, while a list is a set of values.  Some people makethe distinction that a list is a value while an array is a variable.Subroutines are passed and return lists, you put things into listcontext, you initialize arrays with lists, and you foreach() acrossa list.  C<@> variables are arrays, anonymous arrays are arrays, arraysin scalar context behave like the number of elements in them, subroutinesaccess their arguments through the array C<@_>, and push/pop/shift only workon arrays.As a side note, there's no such thing as a list in scalar context.When you say    $scalar = (2, 5, 7, 9);you're using the comma operator in scalar context, so it uses the scalarcomma operator.  There never was a list there at all!  This causes thelast value to be returned: 9.=head2 What is the difference between $array[1] and @array[1]?The former is a scalar value; the latter an array slice, makingit a list with one (scalar) value.  You should use $ when you want ascalar value (most of the time) and @ when you want a list with onescalar value in it (very, very rarely; nearly never, in fact).Sometimes it doesn't make a difference, but sometimes it does.For example, compare:    $good[0] = `some program that outputs several lines`;with    @bad[0]  = `same program that outputs several lines`;The C<use warnings> pragma and the B<-w> flag will warn you about these matters.=head2 How can I remove duplicate elements from a list or array?There are several possible ways, depending on whether the array isordered and whether you wish to preserve the ordering.=over 4=item a)If @in is sorted, and you want @out to be sorted:(this assumes all true values in the array)    $prev = "not equal to $in[0]";    @out = grep($_ ne $prev && ($prev = $_, 1), @in);This is nice in that it doesn't use much extra memory, simulatinguniq(1)'s behavior of removing only adjacent duplicates.  The ", 1"guarantees that the expression is true (so that grep picks it up)even if the $_ is 0, "", or undef.=item b)If you don't know whether @in is sorted:    undef %saw;    @out = grep(!$saw{$_}++, @in);=item c)Like (b), but @in contains only small integers:    @out = grep(!$saw[$_]++, @in);=item d)A way to do (b) without any loops or greps:    undef %saw;    @saw{@in} = ();    @out = sort keys %saw;  # remove sort if undesired=item e)Like (d), but @in contains only small positive integers:    undef @ary;    @ary[@in] = @in;    @out = grep {defined} @ary;=backBut perhaps you should have been using a hash all along, eh?=head2 How can I tell whether a list or array contains a certain element?Hearing the word "in" is an I<in>dication that you probably should haveused a hash, not a list or array, to store your data.  Hashes aredesigned to answer this question quickly and efficiently.  Arrays aren't.That being said, there are several ways to approach this.  If youare going to make this query many times over arbitrary string values,the fastest way is probably to invert the original array and keep anassociative array lying about whose keys are the first array's values.    @blues = qw/azure cerulean teal turquoise lapis-lazuli/;    undef %is_blue;    for (@blues) { $is_blue{$_} = 1 }Now you can check whether $is_blue{$some_color}.  It might have been agood idea to keep the blues all in a hash in the first place.If the values are all small integers, you could use a simple indexedarray.  This kind of an array will take up less space:    @primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);    undef @is_tiny_prime;    for (@primes) { $is_tiny_prime[$_] = 1 }    # or simply  @istiny_prime[@primes] = (1) x @primes;Now you check whether $is_tiny_prime[$some_number].If the values in question are integers instead of strings, you can savequite a lot of space by using bit strings instead:    @articles = ( 1..10, 150..2000, 2017 );    undef $read;    for (@articles) { vec($read,$_,1) = 1 }Now check whether C<vec($read,$n,1)> is true for some C<$n>.Please do not use    ($is_there) = grep $_ eq $whatever, @array;or worse yet    ($is_there) = grep /$whatever/, @array;These are slow (checks every element even if the first matches),inefficient (same reason), and potentially buggy (what if there areregex characters in $whatever?).  If you're only testing once, thenuse:    $is_there = 0;    foreach $elt (@array) {	if ($elt eq $elt_to_find) {	    $is_there = 1;	    last;	}    }    if ($is_there) { ... }=head2 How do I compute the difference of two arrays?  How do I compute the intersection of two arrays?Use a hash.  Here's code to do both and more.  It assumes thateach element is unique in a given array:    @union = @intersection = @difference = ();    %count = ();    foreach $element (@array1, @array2) { $count{$element}++ }    foreach $element (keys %count) {	push @union, $element;	push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;    }Note that this is the I<symmetric difference>, that is, all elements ineither A or in B but not in both.  Think of it as an xor operation.=head2 How do I test whether two arrays or hashes are equal?The following code works for single-level arrays.  It uses a stringwisecomparison, and does not distinguish defined versus undefined emptystrings.  Modify if you have other needs.    $are_equal = compare_arrays(\@frogs, \@toads);    sub compare_arrays {	my ($first, $second) = @_;	no warnings;  # silence spurious -w undef complaints	return 0 unless @$first == @$second;	for (my $i = 0; $i < @$first; $i++) {	    return 0 if $first->[$i] ne $second->[$i];	}	return 1;    }For multilevel structures, you may wish to use an approach morelike this one.  It uses the CPAN module FreezeThaw:    use FreezeThaw qw(cmpStr);    @a = @b = ( "this", "that", [ "more", "stuff" ] );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -