Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Fwd: more splitting travails
- X-seq: zsh-users 29463
- From: Roman Perepelitsa <roman.perepelitsa@xxxxxxxxx>
- To: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- Cc: zsh-users@xxxxxxx
- Subject: Re: Fwd: more splitting travails
- Date: Sat, 13 Jan 2024 06:39:24 +0100
- Archived-at: <https://zsh.org/users/29463>
- In-reply-to: <CAH+w=7Yi+M1vthseF3Awp9JJh5KuFoCbFjLa--a22BGJgEJK_g@mail.gmail.com>
- List-id: <zsh-users.zsh.org>
- References: <ca1761f1-6d8f-452a-b16d-2bfce9076e25@eastlink.ca> <CAH+w=7ZJsr7hGRvD8f-wUogPcGt0DMOcPyiYMpcwCsbBNkRwuQ@mail.gmail.com> <CAA=-s3zc5a+PA7draaA=FmXtwU9K8RrHbb70HbQN8MhmuXTYrQ@mail.gmail.com> <CAH+w=7bAWOF-v36hdNjaxBB-5rhjsp97mAtyESyR2OcojcEFUQ@mail.gmail.com> <205735b2-11e1-4b5e-baa2-7418753f591f@eastlink.ca> <CAH+w=7Y5_oQL20z7mkMUGSLnsdc9ceJ3=QqdAHVRF9jDZ_hZoQ@mail.gmail.com> <CAA=-s3x4nkLST56mhpWqb9OXUQR8081ew63p+5sEsyw5QmMdpw@mail.gmail.com> <CAH+w=7Yi+M1vthseF3Awp9JJh5KuFoCbFjLa--a22BGJgEJK_g@mail.gmail.com>
On Fri, Jan 12, 2024 at 11:09 PM Bart Schaefer
<schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> Yeah, oddly, there's no straightforward way to get an unaltered file
> into a shell variable. Even
> read -rd '' < file
> trims off trailing newlines. The only somewhat-obvious way is to use
> zmodload zsh/mapfile
> var=$mapfile[file]
> but up until a recent dev version, on platforms that don't implement
> memmap that just sneakily reverts to $(<file).
>
> I'm expecting Roman or someone to point out a different trick I've forgotten.
The standard trick here is to print an extra character after the
content of the file and then remove it. This works when capturing
stdout of commands, too.
printf '\n\nA\n\nB\n\n' >file
# read the FULL file content
file_content=${"$(<file && print -n .)"%.} || return
# read the FULL command stdout
cmd_stdout=${"$(cat file && print -n .)"%.} || return
typeset -p file_content cmd_stdout
Unfortunately, these constructs require an extra fork. In
performance-sensitive code the best solution is mapfile or sysread.
They have comparable performance but sysread has the advantage of
being able to read from any file descriptor rather than just a file.
# Reads stdin until EOF and stores all read content in REPLY.
# On error, leaves REPLY unmodified and returns 1.
function slurp() {
emulate -L zsh -o no_multibyte
zmodload zsh/system || return
local content
while true; do
sysread 'content[$#content+1]' && continue
(( $? == 5 )) || return
break
done
typeset -g REPLY=$content
}
printf '\n\nA\n\nB\n\n' >file
slurp <file || return
file_content=$REPLY
slurp < <(cat file) || return
cmd_stdout=$REPLY
typeset -p file_content cmd_stdout
Roman.
Messages sorted by:
Reverse Date,
Date,
Thread,
Author