SCALARs and strings

chomp#

Strip the trailing input record separator from a string in place.

chomp removes any trailing substring that matches the current value of $/ from its argument and returns the total number of characters removed across every argument it touched. It mutates its argument; the return value is a count, not the chomped string. If no argument is given, it operates on $_. chomp is the safer counterpart to chop: it only removes the separator if it is actually there, and it respects $/ so it does the right thing on files that end without a final newline or that use a non-newline record terminator.

Synopsis#

chomp VARIABLE
chomp( LIST )
chomp

What you get back#

The total number of characters removed, as an integer. Usually 0 (no separator was present) or 1 (a single "\n" was removed under the default $/). When $/ is a multi-character string, a successful chomp returns its length. When chomping a list, the count is summed across every element.

The chomped value lives in the variable you passed; chomp is called for effect, not for its return value:

my $line = "hello\n";
my $n = chomp $line;        # $line is "hello", $n is 1

Global state it touches#

  • $/input record separator. chomp reads $/ on every call and strips a trailing occurrence of its current value. Changing $/ changes what chomp removes; this is usually what you want when you set $/ to read custom-delimited records.

  • $_ — consumed as the default argument when chomp is called with no argument. chomp; inside while (<>) { ... } is the canonical idiom.

  • Hash iterator — chomping a hash resets its each iterator (see Edge cases).

Examples#

The everyday use — strip the trailing newline from input:

while (my $line = <$fh>) {
    chomp $line;
    # process $line without the trailing "\n"
}

The no-argument form operates on $_:

while (<>) {
    chomp;                          # removes "\n" from $_
    my @fields = split /:/;
}

Chomp an lvalue assignment — parentheses are required so the argument to chomp is the whole assignment, not just the variable:

chomp(my $cwd    = `pwd`);          # strip "\n" from command output
chomp(my $answer = <STDIN>);        # strip "\n" from user input

Chomping a list — every element is chomped and the total count is returned:

my @lines = ("a\n", "b\n", "no-nl");
my $n = chomp @lines;               # @lines = ("a", "b", "no-nl"), $n = 2

Custom record separator — chomp follows whatever $/ is set to:

local $/ = "\r\n";
my $line = "GET / HTTP/1.0\r\n";
chomp $line;                        # removes "\r\n", returns 2

Paragraph mode — $/ = "" makes chomp remove all trailing newlines from the string:

local $/ = "";
my $para = "line one\nline two\n\n\n";
chomp $para;                        # $para is "line one\nline two"

Edge cases#

  • No separator present: a no-op. Returns 0 and leaves the argument unchanged. This is the whole point of chomp over chop — safe to call on strings that may or may not end in $/.

  • undef argument: chomping an undefined scalar leaves it undefined and returns 0. Under use warnings this emits a uninitialized warning.

  • Hash argument: chomp %h chomps every value (not the keys) and resets the hash’s each iterator. A while (my ($k, $v) = each %h) loop in progress over %h will be disrupted.

  • Slurp mode ($/ = undef) and fixed-length record mode ($/ set to a reference to an integer): chomp removes nothing and returns 0. There is no notion of a trailing separator in these modes.

  • Parenthesisation trap on assignment: without parens, chomp binds tighter than =:

    chomp  $cwd = `pwd`;                # parsed as (chomp $cwd) = `pwd`;
    chomp( $cwd = `pwd` );              # what you meant
    

    Same trap with a bare comma list:

    chomp  $x, $y;                      # parsed as chomp($x), $y;
    chomp( $x, $y );                    # chomps both
    
  • Any lvalue works, not just plain scalars. Array and hash elements, slices, dereferences, and assignment expressions are all legal targets.

  • Constants and read-only values: chomping a read-only string croaks with Modification of a read-only value attempted. String literals are read-only.

  • Multi-byte $/: chomp compares bytes of the string against bytes of $/. If the string and $/ disagree on encoding (one has the UTF-8 flag set, the other does not), the match is done on the internal byte representation and may surprise you. Keep both sides in the same encoding.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • chop — unconditionally remove the last character and return it; older, blunter tool superseded by chomp for input cleanup

  • split — often the next step after chomp, splits the now-trimmed record into fields

  • readline / <> — reads records terminated by $/; chomp undoes the terminator that readline left in place

  • each — the hash iterator that chomp %hash resets

  • $/ — input record separator; chomp reads this on every call

  • $_ — default argument when chomp is called with no explicit target