Printing: print "foo"."\n"."bar"; print "\n"; print "foo","\n","bar"; # equivalent There's a whole thing on using contexts, which reduces to "vibe" \$foo -> reference to a named thing &foo -> subroutine $s = sub {print}; # ref to unnamed subroutine; lambda, essentially *foo -> everything in the symbol table named foo (typeglob) *foo{SCALAR} is the same as \$foo; also available: ARRAY, HASH, CODE, GLOB All nested data structures require references Numbers: - integer and floating point, but sci notation (eN) and underlines are available - octal: 0yyy - hex: 0xyyy - binary: 0byyy Arrays: @home = ("couch","chair","table","stove"); $home[0]; # access ($potato,$life,$tennis,$pipe) = @home; # pattern matching! ($alpha,$omega) = ($omega,$alpha); # happens in parallel, so you can switch like this $wives = ["Leah", "Rachel", "Bilhah", "Zilpah"]; # reference to unnamed array; this is how you put an array into a hash or use a multidimensional array or pass an array to a sub print $$wives[0]."\n"; # have to pull into scalar context; easier with a hash ($wives{"Jacob"}[0]) print $wives->[0]."\n"; # also available for dereferencing arrays $#wives; # last element @midwives = @wives[0..2]; # array slice @middays = @days{"T","W","H"}; # hash slice @doublemid = (@midwives,@middays); # join concat arrays Fns: push, pop, join (array to string), sort, splice (replace, or combine, or whatever) Hashes: From the book: "Until you start thinking in terms of hashes, you aren’t really thinking in Perl"; presumably this is why switch statements weren't added %days = ("U" => "Sunday", "M" => "Monday", "T" => "Tuesday", "W" => "Wednesday", "H" => "Thursday", "F" => "Friday", "S" => "Saturday"); $h = {Foo => bar, Baz => boo}; # ref to unnamed hash Pseudohash: $psh = [ { hash } array ]; allows you to reference by hash or by array (so $psh->[0] and $psh->{key} both work) Fns: keys (extract all), sort (sort keys %x is an idiom), exists $hash{$key}, each (key and value pair) Namespacing: Package foo; # from now on, everything is about foo, and you load things as "foo::" if you want to use them externally Subroutines: used to require a & when called, but was dropped in perl 5; however, it's still used when taking a reference or w/e $s = sub {print (shift);}; # ref to unnamed subroutine; lambda, essentially &$s("foo\n"); $s->("foo\n"); # also available Have to pass arrays/hashes by reference Can pass a hash to have formal parameters Can prototype like so: sub ss ($$){} to be called as ss $a,$b; or sub mypop(\@){} to be called as mypop @arr Switches: -e: execute everything in quotes; this is where oneliners are made :) -n: while (<>) { #-e code here } -p: while (<>) { #-e code; print $_ } You can use BEGIN and END blocks (like awk) to do things at the end of -n/-p And, if you throw in a filename (e.g, perl -ne "code" file.txt), that file gets autoloaded (b/c <>) -a: turn on autosplit; everything goes into @F -F: change field separator for autosplit (like awk) -w: warning messages -c: compile without running -M: load module; -Mmodule = use module; -i: changes input file in-place -d: runs debugger File ops: open $x,mode,file or open $x,file - You can use commands as sources or filters in the two-argument version ("cmd |" or "| cmd") or redirect using & like in bash - Modes: < (input), > (write), >> (append), |- (command that output is piped to), -| (command that input is received from) [these last two are equivalent to the two-argument filters] - You can add a + to have both read/write access - +< - idiomatic rw (<+ would clobber first) Ex: opening a "file" named "gzip -dc < file.gz|" to do all the processing in one script You can also use a reference to a scalar as the file to use that as a pseudofile Filenames can be globbed; you can do @xml = <*.xml>; to find all the xml files in the current directory, or @xml = ; for all the xml files in the docs directory; you can use glob($foo) or <${foo}> to glob a pattern from a variable If you want a single result from a fileglob, use list context (e.g., ($f) = ;) Read lines with <> Fns: chomp, chop Operators: Math: +,-,/,*,%,** Concat: .,x Logic: &&,||,!,and,or,not,xor (yes, there's duplication) Note: all the logic operators short circuit, so you can use them instead of ifs; this is why open(foo,"bar") or die "..."; works You can combine any operator with assignment to make the equiv of +=, so .=, x=, ||=, etc are all on the table Equality: ==,!=,<,>,<=,<=>,eq,ne,lt,gt,le,cmp cmp/<=> is 0 if equal, 1 if left side greater, -1 if right side greater; used for sorting routines, mostly eq,ne,lt,gt,le,cmp are all string comparisons, the others are number comparisons regex: =~,!~ File testing: (e.g., '-e "file.txt" or "..."') -e: file exists -r: file readable -w: file writable -d: directory? -f: file? -T: textfile? Others incl. chdir, defined, exists, gmtime, localtime, rmdir, stat, mkdir, rmdir, opendir Truthiness: All strings are true except "" and "0" All numbers are true except 0 All references are true Any undefined values are false Control flow: if () {} elsif () {} else {} unless () {} while () {} until () {} for () {} # you can just pour an array in here to operate on all of it foreach () {} next; last; # skip or jump to the end of the block You can also use some of them for statement conditionals, e.g., print if x(), print unless x(), etc Regex: //: match Modifiers: i (ignore case), m (^ and $ match next to embedded \n), s (. matches newline), x (ignore whitespace and permit comments in pattern), o (compile pattern once only), g (global), cg (continue after failed global match) s///: substitute Modifiers: same as //, along with e (eval right side as expression) (e.g., s/([0-9]+)/sprintf("%#x", $1)/ge converts all numbers into hex) y///: substitute character-by-character; y/ac/bd/ translates every a to b and every c to d (also tr///); can provide ranges ($message =˜ tr/A-Za-z/N-ZA-Mn-za-m/; # rot13 encryption) Modifiers: c (complement the searchlist), d (delete found but unreplaced characters), s (squash duplicate replaced characters) - Returns # of translations, so you can use it to count # of characters qr//: quote regex (to be assigned to var) You can use s// on $_: $_ = foo; s/o/8/g; works Fns: conditionals, split(//,"") \s: whitespace (tab, newline, return, feed, space \w: [a-zA-Z_0-9] \d: [0-9] Each can be negated by being uppercased, e.g., \D = [^0-9] Quantifiers: \d{7} matches exactly 7 digits, \d{7,11} matches >= 7 but < 11 digits +,*, etc are all greedy by default; you can force nongreedy by adding ? after it (i.e., +?,*?) Boundaries: \b: nonword boundary (b/w word and nonword, zero-width) ^: beginning of line $: end of line Backrefs: In the first part of a match: \1 \2 \3 In the second part and outside: $1 $2 $3 You can also dump them into an array: @x = /(\d+):(\d+):(\d+) *(\w+)/; - Or take @{^CAPTURE} Hot tip: use the smaller regex (e.g., if you want to accept a wide range, write a regex for what you *don't* want, and vice versa) Character escapes: \b: backspace \a: bell \e: esc \cX: C-x \N{name}: unicode name \u: uppercase next char \l: lowercase next char \U: upcase all following chars \L: lowcase all following chars \Q: backlash following nonalphanumeric chars \E: end \U/L/Q Quotes: '': string literal, no interpolate "": string literal, interpolate ``: command, interpolate (): word list, no interpolate //: pattern match, interpolate s///: pattern substitution, interpolate y///: character translation, no interpolate Interpolation: @{[list expression]} (interpolate array) ${\(scalar expression)} (interpolate scalar) Formats: for report generation See ch7 in programming perl, but generally format NAME = # comment or --format@|||^ $arg, $line . Functional style: map foo() @bar; map {} @bar; grep(//,@x); # filter Recursion exists, and you can use it You can compose by just putting them next to each other: "print reverse sort map {lc} keys %hash" works You can create anonymous subroutines (lambdas) and use them, or assign them to variables, or return them from other functions using references Trivia and idioms: while (<>) {} hits ARGV first Reject early cases in a loop with next if (case) /^$/ matches blank lines Early return using logical operators, rather than a million if statements (e.g., $f = $a || $b || $c; Avoid using grep, map, or backticks in a void context, that is, when you just throw away their return values. Those functions all have return values, so use them. Otherwise, use a foreach loop or the system function On windows, quoting sucks. Use q() and qq() instead (slash quoting still works) On windows, you can use Perl to do COM scripting, via win32 OLE Use hashes as switch statements Use pack and unpack for fixed-width data, or for converting to and from different memory representations - possibly good for interop w/ COBOL Hot tips, generally: Instead of making users enter data line by line, pop users into their favorite editor Display the default action at every prompt, and maybe a few alternatives Choose defaults for beginners. Allow experts to change the defaults Use text-oriented network protocols (fuck you, protobuf!) Choose mnemonic identifiers. If you can’t remember what mnemonic means, you’ve got a problem. Write program generators Use files, pipes, and sockets for IPC (run daemons!) Stdlib: # (if you want it, it's probably in there, see https://perldoc.perl.org/modules) File::find (find(1)) various DBM Data::Dumper Pod::Html HTTP::Tiny Documentation: perldoc perldoc -f for a function perldoc -v for a var perldoc -q to search via keywords The Perl book, part 5 (ch28-33) cpan -l for list of installed modules