美文网首页
Chapter 4: Perl One-Liners: Calc

Chapter 4: Perl One-Liners: Calc

作者: 周运来就是我 | 来源:发表于2018-09-21 23:01 被阅读13次

In this chapter, we’ll look at various one-liners for performing calculations, such as

  • finding minimum and maximum elements
  • counting
  • shuffling
  • permuting words
  • calculating dates and numbers.

You’ll also learn about the -a, -M, and -F command-line arguments, the $, special variable, and the @{[ ... ]} construction that lets you run code inside double quotes.

4.1 Check if a number is a prime(质数)
    perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'

比如说,数字7,字串是1111111,匹配11(11)+匹配不了,尝试111(111)+也不行,1111(1111)+也不行,所以是质数;同理,数字9,字串是111111111,匹配11(11)+匹配不上,但是匹配111(111)+可以,所以9是质数。

4.2 Print the sum of all fields on each line
      perl -MList::Util=sum -alne 'print sum @F'

And you wish to find the sum of all these numbers. You can simply specify : as an argument to the -F switch, like this:

    perl -MList::Util=sum -F: -alne 'print sum @F'
4.3 Print the sum of all fields on all lines
        perl -MList::Util=sum -alne 'push @S,@F; END { print sum @S }'

Unfortunately, summing all fields on all lines using this solution creates a massive @S array. A better solution is to keep only the running sum, like this:

    perl -MList::Util=sum -alne '$s += sum @F; END { print $s }'
4.4 Shuffle all fields on each line
  echo a b c d | perl -MList::Util=shuffle -alne 'print "@{[shuffle @F]}"'

to this:

    echo a b c d | perl -MList::Util=shuffle -alne 'print shuffle @F'

You can use the $, special variable to change the separator between array elements when they’re printed. For example, here’s what happens when I change the separator to a colon:

    echo a b c d | perl -MList::Util=shuffle -alne '$,=":"; print shuffle @F'

You can also use the join function to join the elements of @F with a space:

    perl -MList::Util=shuffle -alne 'print join " ", shuffle @F'
4.5 Find the numerically smallest element (minimum element) on each line
      perl -MList::Util=min -alne 'print min @F'
4.6 Find the numerically smallest element (minimum element) over all lines
    perl -MList::Util=min -alne '@M = (@M, @F); END { print min @M }'

If you’re using Perl 5.10 or later, you can do the same thing with this one-liner:

    perl -MList::Util=min -alne '$min = min($min // (), @F); END { print $min }'
4.7 Find the numerically largest element (maximum

element) on each line

    perl -MList::Util=max -alne 'print max @F'
4.8 Find the numerically largest element (maximum

element) over all lines

    perl -MList::Util=max -alne '@M = (@M, @F); END { print max @M }'

If you’re using Perl 5.10 or later, you can use the // operator to shorten this one-liner:

    perl -MList::Util=max -alne '$max = max($max // (), @F); END { print $max }'
4.9 Replace each field with its absolute value
    perl -alne 'print "@{[map { abs } @F]}"'
4.10 Print the total number of fields on each line
    perl -alne 'print scalar @F'
4.11 Print the total number of fields on each line,

followed by the line

    perl -alne 'print scalar @F, " $_"'
4.12 Print the total number of fields on all lines
    perl -alne '$t += @F; END { print $t }' 
4.13 Print the total number of fields that match a pattern
    perl -alne 'map { /regex/ && $t++ } @F; END { print $t || 0 }' 

Looping would be a better approach:

    perl -alne '$t += /regex/ for @F; END { print $t }'

Another way to do this is to use grep in the scalar context:

    perl -alne '$t += grep /regex/, @F; END { print $t }'
4.14 Print the total number of lines that match a pattern
    perl -lne '/regex/ && $t++; END { print $t || 0 }'
4.15 Print the number π
    perl -Mbignum=bpi -le 'print bpi(21)'

The bignum library also exports the constant π, precomputed to 39 decimal places:

      perl -Mbignum=PI -le 'print PI'
4.16 Print the number e
        perl -Mbignum=bexp -le 'print bexp(1,21)' 

For example, you could print the value of e 2 to 30 decimal places:

    perl -Mbignum=bexp -le 'print bexp(2,31)'

As with π, bignum also exports the constant e precomputed to 39 decimal places:

    perl -Mbignum=e -le 'print e'
4.17 Print UNIX time (seconds since January 1, 1970,00:00:00 UTC)
    perl -le 'print time' 
4.18 Print Greenwich Mean Time and local computer time
        perl -le 'print scalar gmtime'

The built-in localtime function acts like gmtime, except it returns the computer’s local time when it’s used in the scalar context:

        perl -le 'print scalar localtime'
图片.png

You can slice this list (that is, extract elements from it) or print individual elements if you need just some part of the information it contains. For example, to print H:M:S, slice the elements 2, 1, and 0 from localtime, like this:

      perl -le 'print join ":", (localtime)[2,1,0]'

To slice elements individually, specify a list of elements to extract, for instance [2,1,0]. Or slice them as a range:

        perl -le 'print join ":", (localtime)[2..6]'

You can also use negative indexes to select elements from the opposite end of a list:

        perl -le 'print join ":", (localtime)[-2, -3]'
4.19 Print yesterday’s date
      perl -MPOSIX -le ' @now = localtime; $now[3] -= 1; print scalar localtime mktime @now'
4.20 Print the date 14 months, 9 days, and 7 seconds ago
      perl -MPOSIX -le ' @now = localtime; $now[0] -=7;  $now[3] -=9;  $now[4] -= 14; print scalar localtime mktime @now'
4.21 Calculate the factorial
      perl -MMath::BigInt -le 'print Math::BigInt->new(5)->bfac()' 

Another way to calculate a factorial is to multiply the numbers from 1 to n together:

    perl -le '$f = 1; $f *= $_ for 1..5; print $f' 
4.22 Calculate the greatest common divisor
    perl -MMath::BigInt=bgcd -le 'print bgcd(20,60,30)'

To calculate the gcd from a file or user’s input, use the -a commandline argument and pass the @F array to the bgcd function:

      perl -MMath::BigInt=bgcd -anle 'print bgcd(@F)'
4.23 Calculate the least common multiple
    perl -MMath::BigInt=blcm -le 'print blcm(35,20,8)' 
4.24 Generate 10 random numbers between 5 and 15 (excluding 15)
    perl -le 'print join ",", map { int(rand(15-5))+5 } 1..10'
4.25 Generate all permutations of a list
    perl -MAlgorithm::Permute -le ' $l = [1,2,3,4,5];$p = Algorithm::Permute->new($l);print "@r" while @r = $p->next'
4.26 Generate the powerset
        perl -MList::PowerSet=powerset -le '  @l = (1,2,3,4,5);  print "@$_" for @{powerset(@l)} '
4.27 Convert an IP address to an unsigned integer
        perl -le '$i=3; $u += ($_<<8*$i--) for "127.0.0.1" =~ /(\d+)/g; print $u'

Here are some more one-liners:

  perl -le '$ip="127.0.0.1";$ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge;print hex($ip)'

You can also use unpack:

    perl -le 'print unpack("N", 127.0.0.1)'

If you have a string with an IP (rather than a vstring), you first have to convert it to byte form with the function inet_aton:

        perl -MSocket -le 'print unpack("N", inet_aton("127.0.0.1"))'
4.28 Convert an unsigned integer to an IP address
    perl -MSocket -le 'print inet_ntoa(pack("N", 2130706433))'

相关文章

网友评论

      本文标题:Chapter 4: Perl One-Liners: Calc

      本文链接:https://www.haomeiwen.com/subject/vdgzzxtx.html