Special variables for Perl

Source: Internet
Author: User
Tags constant regular expression

Transferred from: http://bbs.chinaunix.net/thread-1191868-1-1.html#

To make your Perl code look more like Perl code than a C or basic code, the best thing to do is to understand the built-in variables of Perl. These built-in variables can be used by Perl to control many aspects of the runtime.
In this article, let's take a look at the many built-in variables that perform well on the input and output controls of the file.

Row Count
One of the reasons I decided to write this article was when I found out that a lot of people didn't know "$." The existence of built-in variables, which really surprised me.
I can still see a lot of people writing code like this:
Code


My $line _no = 0;

while (<FILE>) {
+ + $line _no;
Unless (/some regex/) {
Warn "Error in line $line _no/n";
Next
}

# process the record in some
}



For some reason, many people seem to completely ignore the "$." The existence of. The function of this variable is to keep track of the current record number. So the above code can also be written like this:
Code


while (<FILE>)

{
Unless (/some regex/) {
Warn "Error in line $./n";
Next
}

# process the record in some
}




Translator Note: In layman's words, this built-in variable is very similar to the record pointer in the database, and its value is the current line number in the file you are currently reading.

Although using this built-in variable does not allow you to hit much less, it is important that we omit some unnecessary variable declarations.
Another way to take advantage of this built-in variable is with the continuous operator (..) Used together. When used in the context of a list, the (..) is a list build operator. It creates all the elements from the given start and end elements. For example:
Code


My @numbers = (1.. 1000);


@numbers will contain all the integers from 1 to 1000.


But when you use this action in the context of an expression (for example, as a condition of a declaration), it is completely different. First operand ("..." The left side of the expression) will be evaluated, and if the resulting value is false, this operation will do nothing and return false values. If the resulting value is true, the operation returns truth and continues to return the following value until the second operand (".."). The expression to the right of the operator) returns the true value.
Let's give an example to explain. Suppose you have a file that you only want to work with some parts of the file. These parts take "!! START!! " For the beginning, "!! END!! " To the end.
With continuous operators you can write this code like this:
Code


while (<FILE>) {
if (/!! START!! / .. /!! END!! /) {
# Process Line
}
}




Each cycle, the continuous operator checks the current line. If the current line and the/!! START!! /"does not match, the operator returns a false value and continues the loop. When looping to the first with/!! START!! /"matches the row, the continuous operator returns the truth and executes the code in the IF statement block. In the loop after the while statement, the continuous operator checks again "/!! END!! /", but it will not return true until a matching row has been found. That means in "!! START!! "and"!! END!! "All lines between the tags will be processed. When we find/!!. END!! /Match row, the continuous operator returns false and starts again to match the first rule expression.

These with "$." What's the matter with it. If one of the operands of a continuous operator is a constant, they will be converted to an integer number and "$." The.
So outputting the first 10 lines of a file we can write code like this:
Code


while (<FILE>) {
Print if 1.. 10;
}



About "$." The last point to note is that there is only one "$" in a program. Variable. If you are reading data from multiple file handles, then "$." Variable holds the current record number in the most recently read file handle. If you want a more complex way to solve this problem then you can use a similar Io::file object. These objects all have a Input_line_number method.

Record delimiter

"$/" and "$/" are input and output record separators respectively. When you are reading or writing data, they primarily control what is used to define a "record."

Let me explain it to you in more detail. When you first learned about Perl and the first time you knew the file input operator, you might be told that "<FILE>" is reading from a file
into one row of data, and each row that is read into contains a new line character ("/n"). What you know is not entirely true, it's just a very special situation. In fact, the file input operator ("<>") reads the data and contains a file input delimiter specified in "$/". Let's look at an example:

Suppose you have a text file with interesting citations or some lyrics or something else. For example, something like the following:
Code


The definition of my life
%%
We is far too young and clever
%%
Stab a Sorry Heart
With your favorite finger



Here are three quotations separated by a line of "percent". So how do we read a quote from this file one at a time? (Translator Note: This quotation is a line can also be a few lines, such as the first paragraph in the example and the second citation is a row, and the third quotation is 2 lines)
One solution is to read one row from a file at a time, and then check that the read-in line is "percent". So we need to declare a variable to hold the data for each read, and then regroup the previously read data into a complete citation when "percent" is encountered. Oh, you also need to remember to deal with the last quotation because it has no "percent" at the end.
This approach is too complex, and an easy way to do this is to change the contents of the "$/" variable. The default value of this variable is a new line character ("/n"), which is why the "<>"
The operator reads the contents of a file one line at a time. But we can change the content of this variable to whatever value we like. Like what:

Code


$/= "%%/n";

while (<QUOTE>) {
Chomp
Print
}



Now every time we call "<>", Perl reads the data one time from the file handle until "%%/n" is found. (not read one line at a time).
Therefore, when you use the Chomp function to remove the row delimiter that reads the data, the delimiter specified in the "$/" variable is removed. The data after the Chomp function has been processed in the example above will
%%/n "Delete.

Change special variables for Perl

Before we go on, I need to remind you that when you modify the values of these special variables, you get a warning. The problem is that most of these variables are forced in the main package
Of That is, when you change the values of these variables, the place where the value is used in the program (including the modules you include) gives a warning.
For example, if you are writing a module and you change the value of the "$/" variable in the module, you must modify the other modules when others apply your module to your program.
To suit the execution of the program. So modifying the value of a special variable potentially increases the difficulty of finding bugs.

So we should try to avoid it as much as possible. The first way to avoid this is to re-value the special variable back to its original value after you have exhausted the value of the modified special variable. Like what:
Code


$/= "%%/n";

while (<QUOTE>) {
Chomp
Print
}

$/= "/n";



Another problem with this approach is that you cannot be sure that its value is the system default before you reset the value of the special variable.
(Translator Note: For example if you are in "$/="%%/n ";") The value of the "$/" variable (not the default value "/n") has been modified before, and you will definitely throw an error when you finally reset the default value)
So our code should look like this, as follows:
Code


$old _input_rec_sep = $/;
$/= "%%/n";

while (<QUOTE>) {
Chomp
Print
}

$/= $old _input_rec_sep;




The above code avoids the bug we mentioned above, but we have another method that looks more concise. This method uses local to define the "$/" variable. As follows:
Code


{
Local $/= "%%/n";

while (<QUOTE>) {
Chomp
Print
}
}



We enclose the code in a pair of curly braces. In general, code blocks are often associated with loops, conditions, or subroutines, but in Perl you can use curly braces to illustrate a block of code alone.
Variables defined in this code block with local only work in the current block of code.
In summary, it is a good practice not to change the built-in variables of Perl unless it is localized in a block of code.


Other values for "$/"

Here are some special values you can give to "$/" variables that can open some interesting behavior. The first one is to set the variable to undefined. This will turn on Slurp mode,
When this mode is turned on, we can read all the contents of the file from one file at a time. As follows:
Code


My $file = do {local $/; <FILE>};



The return value of a Do statement block is the value of the last expression in the statement block, as the return value of the DO statement block above is the return value of the "<>" operator. And since the "$/" variable is set to undef (undefined), the contents of the entire file are returned. It is important to note that we do not need to explicitly specify the "$/" variable as undef, because all Perl variables are automatically initialized to undef when they are defined.

Setting the "$/" variable to undef and null is very different: setting to null means turning on paragraph mode (that is, paragraph mode), where each record is a paragraph of text that ends with one or more empty behaviors. You might think that this effect is the same as the effect of setting the "$/" variable to "/n/n", but they still have a subtle difference. If comparisons are made, then the "$/" variable should be set to "/n/n+" to be the same as the paragraph mode. (Note that this is just for example.) In fact, the "$/" variable cannot be set to a regular expression) the last special value of the "$/" variable is that it can be set to a reference to an integer scalar variable or to a reference to an integer constant.
In this case, the data that is read out each time from the file handle is the size specified by the "$/" variable. (Here I say "most" because it is possible that the remaining data size at the end of the file is less than the size specified by the "$/" variable). So if you want to read 2kb of data every time then you can do this:
Code


{
Local $/=/2048;

while (<FILE>) {
# $_ contains the next 2048 bytes from FILE
}
}




"$/" and "$."


Notice that when changing the value of the "$/" variable, the Perl definition of the record is changed accordingly. The behavior of the variable. "$." The variable is not actually saved as the current "line" number, but the current record number. So in the example of that citation mentioned above, "$." The variable is incremented for each segment of the file that you want to read the data from.

About "$/"

At the beginning of the previous I mentioned "$/" and "$/" variables as the record separators for input and output. However, we have not introduced the "$/" variable.

To tell the truth, "$/" is not as useful as "$/". It contains the string to increment at the end of each call to the print output.
Its default value is an empty string, so when you output with print, nothing follows the output data. Of course if you really want to have a Pascal-like output function println, then we can write:

Code


Sub println {
Local $/= "/n";
Print @_;
}


This adds a "/n" (that is, a newline character) behind the data every time you print the data with printing.

Other Print variables

The next two variables that need to be discussed are very easy to confuse, although they do two things that are completely different. For illustrative purposes, look at the following code:
Code


My @arr = (1, 2, 3);

Print @arr;
print "@arr";



Now, if you are not careful to see if you know the difference between the above two print calls.
The answer is that the first print call is next to the three elements of the output array, without any delimiters (the output is: 123). However, the second print statement outputs elements that are indeed separated by spaces (the output is: 1 2 3). Why is there such a difference?

The key to understanding this problem is what is actually passed to the print call in each case. In the first case, the one passed to print is an array. Perl will expand the array passed over as a list of three elements in the list that are treated as separate parameters. In the second case, the array is enclosed in double quotation marks before being passed to print.
In fact, the second case can also be understood as follows:
Code


My $string = "@arr";
Print $string;


So, in the second case, it's just a parameter passed to the print function. The fact is that the inclusion of a double quotation mark on an array does not affect how the print function treats the string.



So there are two things in front of us. When print receives a set of parameters, it will compactly output the parameters without spaces between the output parameters. When an array is
Before the double quotation marks are passed to print, each element of the array expands to a string as a space delimiter. These two situations are completely irrelevant. But from the example we've given above, it's easy to see how people confuse the two situations.
Of course, if we want, Perl allows us to change this behavior. The "$," variable holds the string used to separate the arguments passed to the print function. As described above, the character of the default split print parameter is a null character, which can be changed, of course:

Code


My @arr = (1, 2, 3);
{
Local $, = ', ';

Print @arr;
}


This code will output


Accordingly, when an array is passed to the print function by double quotation marks, the character that is used to split the element after the array is expanded is saved in the "$" variable. The code is as follows:

Code


My @arr = (1, 2, 3);
{
Local $ "= ' + ';

print "@arr";
}


This code will output 1+2+3



Of course, the "$" variable is not required in the use of a print statement. You can use any of the enclosed arrays in double quotes. And it's not just an array to be effective.

can also be used on a hash table.
Code


My%hash = (one = 1, and 2, three and 3);

{
Local $ "= ' < ';

Print "@hash {QW (one three)}";
}


This will output: 1 < 2 < 3

http://bbs.chinaunix.net/thread-1191868-1-1.html#

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.