Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Minimal Perl For UNIX and Linux People 8 docx
MIỄN PHÍ
Số trang
58
Kích thước
449.0 KB
Định dạng
PDF
Lượt xem
1382

Minimal Perl For UNIX and Linux People 8 docx

Nội dung xem thử

Mô tả chi tiết

298 CHAPTER 9 LIST VARIABLES

As shown in the table’s last row, the Shell uses the special @ index to retrieve all values,

preserve any whitespace within them, and separate them from each other by a space.

As usual, double quotes are also required if further processing of the extracted values

isn’t desired.

With Perl, on the other hand, all values are retrieved by using the array name with￾out an index. The only effect of the double quotes is to separate the values on output

with the contents of the ‘$"’ variable—they’re not needed to suppress further process￾ing of the extracted values, because that doesn’t happen anyway.2

Next, we’ll look at different ways to initialize arrays.

Table 9.2 Syntax for using arrays in the Shell and Perl

Shell Perl a Remarks

Assigning a value n[0]=13 $n[0]=13; In Perl, the $ symbol is always

used with the variable name

when referring to a scalar value.

With the Shell, it’s only used

when retrieving a value.

Retrieving and

displaying a value

echo ${n[0]} print $n[0]; The Shell requires the array name

and index to be enclosed in curly

braces.

Deleting a value unset n[0] delete $n[0]; The Shell deletes the designated

element, but Perl maintains the

element’s slot after marking its

value as undefined.

Assigning multiple

values

n=(13 42) @n=(13, 42);

@n=qw/13 42/;

@n=qw!\ | /!;

The Shell recognizes whitespace

as separators in the parenthe￾sized list of initializers. By default,

Perl requires a comma, and

allows additional whitespace.

With the qwX syntax, only

whitespace separators are recog￾nized between paired occur￾rences of the X delimiter.b

Retrieving and

displaying all values

echo "${n[@]}" print "@n"; See text for explanation.

a. The examples using print assume the use of Perl’s l invocation option.

b. Examples of the qwX quoting syntax are shown in chapter 12.

2 See http://TeachMePerl.com/DQs_in_shell_vs_perl.html for details on the comparative use of double

quotes in the two languages.

USING ARRAY VARIABLES 299

9.1.1 Initializing arrays with piecemeal

assignments and push

As shown in the top row of table 9.2, you can initialize arrays in piecemeal fashion:

$stooges[2]='Curly';

$stooges[0]='Moe';

$stooges[1]='Larry';

Alternatively, you can use explicit lists on both sides of the assignment operator:

($stooges[2], $stooges[0], $stooges[1])=('Curly', 'Moe', 'Larry');

When it’s acceptable to add new elements to the end of an array, you can avoid man￾aging an array index by using push @arrayname, 'new value'. This technique

is used in the shell_types script, which categorizes Unix accounts into those

having human-usable shells (such as /usr/bin/ksh) or “inhuman” shells (such as

/sbin/shutdown):

$ shell_types | fmt -68 # format to fit on screen

THESE ACCOUNTS USE HUMAN SHELLS: root, bin, daemon, lp, games,

wwwrun, named, nobody, ftp, man, news, uucp, at, tim, yeshe, info,

contix, linux, spug, mailman, snort, stu01

THESE ACCOUNTS USE INHUMAN SHELLS: mail, sshd, postfix, ntp, vscan

Because the listing of “human” account names produces a very long line, the Unix

fmt command is used to reformat the text to fit within the width of the screen.

The script’s shebang line (see listing 9.1) arranges for input lines to be automati￾cally split into fields on the basis of individual colons, because that’s the field separa￾tor used in the /etc/passwd file, which associates shells with user accounts.

The matching operator on Line 8 checks the last field of each line for the pattern

characteristic of “human” shells and stores the associated account names in @human

using push. Alternatively, Line 12 arranges for the names of the accounts that fail the

test to be stored in @inhuman.

1 #! /usr/bin/perl -wnlaF':'

2

3 BEGIN {

4 @ARGV=( '/etc/passwd' ); # Specify input file

5 }

6

7 # Separate users of "human" oriented shells from others

8 if ( $F[-1] =~ /sh$/ ) {

9 push @human, $F[0];

10 }

11 else {

12 push @inhuman, $F[0];

13 }

Listing 9.1 The shell_types script

300 CHAPTER 9 LIST VARIABLES

14 END {

15 $"=', ';

16 print "\UThese accounts use human shells: \E\n@human\n";

17 print "\UThese accounts use inhuman shells:\E\n@inhuman";

18 }

To make the output more presentable, Line 15 sets the ‘$"’ variable to a comma-space

sequence, and \U is used to convert the output headings to uppercase.

In programs like this, where you don’t care what position a data element is allo￾cated in the array, it’s more convenient to push them onto the array’s end than to

manage an index. In other cases, it may be more appropriate to do piecemeal array￾initializations using indexing (see, e.g., section 10.5), to maintain control over where

an element is stored.

Next, we’ll look at the syntax and rules for using more advanced indexing

techniques.

9.1.2 Understanding advanced array indexing

Table 9.3 shows the association between array values and indices of both the positive

and negative varieties, both of which are usable in Perl. Negative indexing counts

backward from the end of the array and is most commonly used to access an array’s

last element. Another way to do that is by using an array’s maximum index variable,

whose name is $#arrayname.

Table 9.3 Syntax for advanced array indexing

Initialization @X=('A', 'B', 'C', 'D');

Stored value A B C D

Ordinal Position 1 2 3 4

Positive indexing $X[ 0] $X[ 1] $X[ 2] $X[ 3]

Negative indexing $X[-4] $X[-3] $X[-2] $X[-1]

Indexing with maximum-index variable $X[$#X]

Result A B C D

Slice indexing @X[2,3] "@X[2,0..1]" @X[3,0..2]

Result CD C A B DABC

USING ARRAY VARIABLES 301

As an alternative to repeatedly indexing into an array to access several values, Perl

allows a collection of values—called an array slice3—to be addressed in one indexing

expression (as shown in the table’s bottom panel). You do this by arranging the

comma-separated indices within square brackets in the order desired for retrieval (or

assignment) and putting @arrayname before that expression. The @ symbol is used

rather than $, because multiple indices extract a list of values, not a single scalar value.

You can also specify a range of consecutive indices by placing the range operator

(..) between the end points, allowing the use of 3..5, for instance, as a shortcut for

3, 4, 5.

The following Perl command retrieves multiple values from an array using a slice:

$ cat newage_contacts # field number exceeds index by 1

(510) 246-7890 [email protected]

(225) 424-4242 [email protected]

(928) 312-5789 [email protected]

1/0 2/1 3/2

$ perl -wnla -e 'print "@F[2,0,1]";' newage_contacts

[email protected] (510) 246-7890

[email protected] (225) 424-4242

[email protected] (928) 312-5789

We could have written the Perl command without using an array slice, by typing

print "$F[2] $F[0] $F[1]" in place of print "@F[2,0,1]". But that involves

a lot of extra typing, so it’s not Lazy enough!

Because each array slice is itself a list, you can set the ‘$"’ formatting variable to

insert a custom separator between the list elements:

$ perl -wnla -e '$"=":\t"; print "@F[0,2]";' newage_contacts

(510): [email protected]

(225): [email protected]

(928): [email protected]

We’ll continue with this theme of finding friendlier ways to write array-indexing

expressions in the next section, where you’ll see how a script that lets the user think

like a human makes access to fields a lot easier.

9.1.3 Extracting fields in a friendlier fashion

Sooner or later, every Perl programmer makes the mistake of attempting to use 1 as the

index to extract the first value from an array—rather than 0—because humans natu￾rally count from 1. But with a little creative coding, you can indulge this tendency.

3 The indexed elements needn’t be adjacent, and subsequent slices needn’t run parallel to earlier ones (as

with bread slices), so a better name for this feature might be an index group.

Field numbers / indices

302 CHAPTER 9 LIST VARIABLES

As a case in point, the show_fields2 script allows the user to select fields for dis￾play using human-oriented numbers, which start from 1:

$ cat zappa_floyd

Weasels Ripped my Flesh Frank Zappa

Dark Side of the Moon Pink Floyd

$ show_fields2 '1' zappa_floyd # 1 means first field

Weasels

Dark

It works by using unshift (introduced in table 8.2) to prepend a new value to the

array, which shifts the existing values rightward. As a result, the value originally stored

under the index of N gets moved to N+1.

As depicted in Figure 9.1, if 0 was the original index for the value A, after

unshift prepends one new item, A would then be found under 1.

The show_fields2 script also supports index ranges and array slices:

$ cat zappa_floyd # field numbers added

Weasels Ripped my Flesh Frank Zappa

1 2 3 4 5 6

Dark Side of the Moon Pink Floyd

1 2 3 4 5 6 7

$ cat zappa_floyd | show_fields2 '2..4,1' # indices 1..3,0

Ripped my Flesh Weasels

Side of the Dark

It even issues a warning if the user attempts to access (the illegitimate) field 0:

$ show_fields2 '0' zappa_floyd # WRONG!

Usage: show_fields2 '2,1,4..7, etc.' [ file1 ... ]

There's no field #0! The first is #1.

The show_fields2 script, which uses several advanced array-handling techniques,

is shown in listing 9.2.

Line 7 pulls the argument containing the field specifications out of @ARGV and

saves it in the $fields variable. Then, a matching operator is used to ask whether

Figure 9.1 Effect of unshift

Field numbers

Tải ngay đi em, còn do dự, trời tối mất!