Home > front end >  Count trailing newlines with POSIX utilities or Perl
Count trailing newlines with POSIX utilities or Perl

Time:01-07

I'm looking for ways to count the number of trailing newlines from possibly binary data either:

  • read from standard input
  • or already in a shell variable (then of course the "binary" excludes at least 0x0) using POSIX or coreutils utilities or maybe Perl.

This should work without temporary files or FIFOs.

When the input is in a shell variable, I already have the following (possibly ugly but) working solution:

original_string=$'abc\n\n\def\n\n\n'
string_without_trailing_newlines="$( printf '%s' "${original_string}" )"
printf '%s' $(( ${#original_string}-${#string_without_trailing_newlines} ))

which gives 3 in the above example.

The idea above is simply to subtract the string lengths and use the "feature" of command substitution that it discards any trailing newlines.

CodePudding user response:

Some perl based solutions:

#!/usr/bin/env bash

original_string=$'abc\n\n\ndef\n\n\n'

# From a shell variable. Look ma, no pipes!
input="$original_string" perl -E '$ENV{input} =~ /(\n*)\z/; say length $1'

# From standard input (Note: The herestring adds an extra newline)
perl -0777 -nE '/(\n*)\z/; say length($1) - 1' <<<"$original_string"

# Or in a shell without herestrings (But then you're also not getting the
# above $'' quoting syntax)
printf "%s" "$original_string" | perl -0777 -nE '/(\n*)\z/; say length $1' 

CodePudding user response:

Is this what you want (using GNU awk)?

$ printf 'ab\0c\n\0\n\d\0ef\n\n\n' | awk '/./{n=NR-1} END{print NR-n}'
3

CodePudding user response:

If the string is stored in variable a, with GNU sed:

$ a=$'abc\n\n\ndef\n\n\n'
$ b=$(sed -z 's/\n*$//' <<< "$a")
$ echo $(( ${#a} - ${#b} ))
3

If it comes from the standard input first pipe it to a=$(cat). Example:

$ printf 'abc\n\n\ndef\n\n\n' | a=$(cat)
$ b=$(sed -z 's/\n*$//' <<< "$a")
$ echo $(( ${#a} - ${#b} ))
3
  •  Tags:  
  • Related