# The switches Every one-liner is a combination of a program (passed to `-e` or `-E`) and a handful of switches that wrap implicit behaviour around it. This chapter covers the switches you will reach for. Each one earns its keep in the progression, regex, and numeric chapters that follow. Readers coming from `awk` or `sed` already know what per-line iteration, field splitting, and in-place editing look like; the question is which pperl flag turns each on. ## `-e` — run a program given on the command line ```bash pperl -e 'print "hello\n"' ``` `-e` takes the Perl source as its argument. Multiple `-e` chunks concatenate; they behave as one program with semicolons between them. ```bash pperl -e 'my $x = 41;' -e 'print $x + 1, "\n"' # 42 ``` Use single quotes around the program so the shell leaves `$_`, `$1`, `\n`, and backticks alone. See [gotchas](quoting) for what goes wrong with double quotes. ## `-E` — `-e` plus the modern feature set `-E` is `-e` with all optional features enabled: [`say`](../../p5/core/perlfunc/say), `state`, [`fc`](../../p5/core/perlfunc/fc), the `//` defined-or operator, unicode string semantics under `use feature 'unicode_strings'`, and more. ```bash pperl -E 'say "hello"' # instead of print "hello\n" pperl -E 'say "pi = " . (atan2(1,1)*4)' ``` Reach for `-E` when writing new one-liners. Reach for `-e` only when copy-paste compatibility with very old scripts matters. ## `-n` — wrap an implicit read loop around the program `-n` turns the program into the body of a loop over every line of every input file (or STDIN if none are given). The loop is exactly: ```perl while (<>) { # your program } ``` `$_` holds each input line, including its trailing newline. Nothing is printed automatically — you decide what reaches STDOUT. ```bash # Print lines containing "error" pperl -ne 'print if /error/' app.log ``` Equivalent long form, shown once so the mechanical expansion is clear: ```perl while (<>) { print if /error/; } ``` Every subsequent `-n` recipe in this guide relies on that expansion — assume it without re-stating. `BEGIN { … }` runs before the loop, `END { … }` runs after. Both are ordinary Perl blocks and compose with `-n` cleanly. ```bash # Count lines matching a pattern pperl -ne '$n++ if /WARN/; END { print "$n\n" }' app.log ``` ## `-p` — like `-n`, but print `$_` after each iteration ```bash pperl -pe 's/foo/bar/g' input.txt ``` Mechanical expansion: ```perl while (<>) { # your program } continue { print or die "-p destination: $!"; } ``` Reach for `-p` when the output is the (possibly modified) input. Reach for `-n` when the output is a summary, a filtered subset, or nothing at all. ## `-l` — line-end handling `-l` does two things at once: 1. On input, [`chomp`](../../p5/core/perlfunc/chomp) each line as it is read under `-n` / `-p`. `$_` no longer ends in `"\n"`. 2. On output, set `$\` (the output record separator) so every [`print`](../../p5/core/perlfunc/print) appends `"\n"`. ```bash # Print just the first field of each tab-separated line pperl -F'\t' -lane 'print $F[0]' table.tsv ``` Without `-l`, you would either write `print "$F[0]\n"` (the newline moves into the program) or produce glued output. `-l` accepts an optional octal argument that sets `$\` to a different character: `-l012` keeps newline (the default), `-l0` sets `$\` to NUL, and so on. The common use is the no-argument form. ## `-a` — autosplit into `@F` Combined with `-n` or `-p`, `-a` splits `$_` on whitespace and puts the fields into `@F`. The default split is [`split(' ', $_)`](../../p5/core/perlfunc/split) — it trims leading whitespace and treats any run of whitespace as one separator. ```bash # Third column of every line pperl -lane 'print $F[2]' data.txt # Reverse column order pperl -lane 'print "@{[reverse @F]}"' data.txt ``` `@F` is zero-indexed. `$F[-1]` is the last field. `scalar @F` is the field count. ## `-F` — change the split pattern `-F` sets the delimiter used by `-a`. The argument is a regex; a literal comma is `-F,`, a colon is `-F:`, a tab is `-F'\t'`. ```bash # Second field of a colon-separated file pperl -F: -lane 'print $F[1]' /etc/passwd # Split on any run of commas or semicolons pperl -F'[,;]+' -lane 'print scalar @F' mixed.csv ``` `-F` implies nothing about `-a`; you still need `-a`. The common idiom `-F: -lane` is colon-split, chomped, with `@F` available. Quoting a tab requires a literal tab in the shell or the regex form: ```bash pperl -F'\t' -lane 'print $F[0]' data.tsv # regex form, always safe pperl -F' ' -lane 'print $F[0]' data.tsv # literal tab — fragile ``` ## `-i` — edit files in place `-i` rewrites the file `pperl` is reading from, replacing its contents with whatever `-p` prints. The whole file's output goes to a temporary file; when the loop finishes, that temporary replaces the original. ```bash # Replace CRLF with LF in every .txt under cwd (no backup) pperl -i -pe 's/\r\n/\n/g' *.txt # Same, keeping a .bak copy beside each original pperl -i.bak -pe 's/\r\n/\n/g' *.txt ``` **Always use `-i.bak`** (or another suffix) until you have verified the edit against a representative file. A bug in the program with bare `-i` destroys the input. See [gotchas](in-place-edit). `-i` has no effect without `-p` (or explicit prints under `-n`): if nothing is printed, the replacement file is empty. ## `-M` and `-m` — load modules before the program runs `-Mmodule` is equivalent to `use module;` at the top of the program. `-Mmodule=sym1,sym2` is `use module qw(sym1 sym2);`. ```bash pperl -MList::Util=sum -lane 'print sum @F' data.txt pperl -MPOSIX=strftime -le 'print strftime("%F", localtime)' pperl -MData::Dumper -e 'print Dumper({a=>1, b=>[2,3]})' ``` Lower-case `-m` is `no strict …` rather than `use …`; it is rarely needed on the command line. Modules most common in one-liners: `List::Util` (sum/min/max/uniq/any), `POSIX` (strftime, mktime, fmod), `Data::Dumper` (inspect structures), `JSON::PP` (parse/emit JSON), `Text::CSV` (quoted CSV), `MIME::Base64`, `Digest::MD5`, `Digest::SHA`, `Socket`. ## `-0` — set the input record separator Perl normally reads a line at a time. `-0NNN` sets `$/` to the character with the given octal code, changing what "one record" means for [`<>`](../../p5/core/perlop), [``](../../p5/core/perlop), and the `-n` / `-p` loop. Common forms: | Form | What `$/` becomes | Effect | |----------|-------------------|------------------------------------------------------| | `-0` | `"\0"` (NUL) | Read NUL-delimited records (matches `find -print0`). | | `-0777` | `undef` | Slurp the whole file as one record. | | `-00` | `""` | Paragraph mode: blank lines separate records. | | `-0NNN` | `chr(0NNN)` | Any single octal byte. | ```bash # Count files from find -print0 find . -type f -print0 | pperl -0 -ne '$n++; END { print "$n\n" }' # Slurp, then run a cross-line regex pperl -0777 -ne 'print "yes\n" if /BEGIN.*?END/s' text.txt # Print every paragraph containing "TODO" pperl -00 -ne 'print if /TODO/' notes.txt ``` Paragraph mode (`-00`) interacts with `-l`: without `-l`, the blank separator stays attached to each record; with `-l`, it is chomped. (c-unicode)= ## `-C` — Unicode on stdio and/or `@ARGV` `-C` enables Unicode handling on specified streams. The argument is either a number (bitmask) or a string of letters. ```bash pperl -CSD -ne 'print' input.txt # stdin, stdout, stderr all UTF-8 pperl -CA -e 'print $ARGV[0]' äöü # @ARGV treated as UTF-8 pperl -CSA -nE 'say length' # S + A ``` Letter codes: `I` = stdin, `O` = stdout, `E` = stderr, `S` = `I`+`O`+`E`, `A` = `@ARGV`, `D` = set default I/O layers (includes file opens). For a fully UTF-8 session, `-CSD`. For one-off processing of named UTF-8 files, `-CSAD`. See [gotchas](encoding) for the symptoms that tell you `-C` is missing. (reference-table)= ## Reference table Every switch, its mechanical expansion, and the chapter where it first shows up in a recipe. | Switch | Expands to | First used in | |-----------|-----------------------------------------------------------|-----------------------------------------------| | `-e CODE` | Run CODE as the program | [progression](baseline) | | `-E CODE` | `-e` plus all current features enabled | [progression](baseline) | | `-n` | `while (<>) { CODE }` | [progression](filtering) | | `-p` | `while (<>) { CODE } continue { print }` | [progression](substitution) | | `-l` | `chomp` input under `-n`/`-p`; set `$\ = "\n"` for output | [progression](fields) | | `-a` | Auto-split `$_` into `@F` | [progression](fields) | | `-F PAT` | Change `-a` split pattern to regex `PAT` | [progression](fields) | | `-i[EXT]` | Edit in place; with `EXT`, keep backup `original + EXT` | [progression](in-place) | | `-M MOD` | `use MOD;` before program | [numeric](sum-min-max) | | `-M MOD=X`| `use MOD qw(X);` | [numeric](sum-min-max) | | `-0` | `$/ = "\0"` — NUL-delimited records | [progression](records) | | `-00` | `$/ = ""` — paragraph mode | [progression](records) | | `-0777` | `$/ = undef` — slurp entire file | [progression](records) | | `-C` | Enable Unicode on stdio, `@ARGV`, and/or default layers | [gotchas](encoding) | ## Special variables the switches set up Short catalogue; full definitions live in [`perlvar`](../../p5/core/perlvar). | Variable | Role under `-n`/`-p` | |----------|-------------------------------------------------------------------------| | `$_` | The current input line (chomped if `-l`, raw otherwise). | | `$.` | Current input line number (not reset between files by default). | | `$/` | Input record separator. `-0` family changes it. | | `$\` | Output record separator appended by `print`. `-l` sets it to `"\n"`. | | `$,` | Output field separator inserted between `print`'s arguments. | | `$"` | Separator between array elements when interpolated in `"@array"`. | | `@F` | Auto-split fields under `-a`. | | `@ARGV` | Remaining command-line arguments; filenames are consumed as processed. | | `$ARGV` | Name of the file currently being read (`"-"` means STDIN). | ## Find out more - [progression](progression) applies every switch in recipes of increasing complexity. - [`perlvar`](../../p5/core/perlvar) lists every special variable pperl defines, not just the ones the switches touch. - [`perlop`](../../p5/core/perlop) covers `qr//`, the flip-flop operator, and the diamond operator used by the `-n` / `-p` loops.