Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: keep empty lines at the end of files?



On Sat, Feb 03, 2007 at 12:52:37PM -0800, Bart Schaefer wrote:
> On Feb 2, 10:03am, Marc Chantreux wrote:
> }
> } I have some files with very important empty lines at the end of them.
> } 
> } Is the a clean and short way to *not* trim the file ?
> 
> zmodload -i zsh/mapfile
> content=${mapfile[ldap_user_passwd]}
> 
> I'm not sure, historically speaking, why $(<...) is trimming trailing
> blank lines.

It makes sense to trim *one* newline character, because for most
commands, there's one newline added by the command to the data
it is actually displaying.

In

base=$(basename -- "$file")

You don't want in $base the trailing newline character added by
basename. However, you want the ones before because those ones
are part of the filename.

However all the Bourne and csh like shells have always removed
*every* trailing newline character. I personally consider it as
a bug.

A work around for POSIX shells is:

cmdoutput() {
  REPLY=$(eval "$1"; echo .)
  REPLY=${REPLY%?.}
}

For Bourne shells:

cmdoutput() {
  REPLY=`
    eval "$1" | sed "s/'/'\\\\\\\\''/g;\\\$s/\\\$/'/"
  `
  eval "REPLY='$REPLY"
}

In rc, it's a bit more consistent, but not much more usable.

First in rc, all variables are lists, so

var = `{ls}
(first, quite sensibly, filename generation is not performed as
in zsh)

Then the output of ls is split and stored into the $var list.
The splitting algoithm is a lot simpler and more consistent than
in Bourne like shells, A sequence of separators is a separator
and leading and trailing separators are discarded whatever they
are (like in sh for the whitespace separators).

So, the trailing characters are removed as part of the word
splitting in rc.

That means

var = `{basename -- $file}

is no more correct than is Bourne like shells (even less correct
as the command output is split).

However, in rc, one can explicitely specify the separator:

var = ``(separators){cmd}

So

var = ``(){cmd}

captures exactly the output of cmd (as long as it doesn't
contain null bytes as all rc variables are environment
variables).

Now, if you want to remove the trailing newline character, it
ends up being as difficult as having a correct behavior in sh.

var = ``(){cmd | awk 'NR>1{print ""}{printf "%s", $0}'}

GNU only:
var = ``(){cmd | head -c-1}

In es (based on rc):

var = <={~~ ``(){cmd} *\n}

So the question remains. Why hasn't any single shell come up
with the correct solution?

-- 
Stéphane



Messages sorted by: Reverse Date, Date, Thread, Author