Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Slurping a file (was: more spllitting travails)
- X-seq: zsh-users 29468
- From: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- To: Zsh Users <zsh-users@xxxxxxx>
- Subject: Slurping a file (was: more spllitting travails)
- Date: Sat, 13 Jan 2024 12:02:06 -0800
- Archived-at: <https://zsh.org/users/29468>
- In-reply-to: <CAN=4vMpexntEq=hZcmsiXySy-2ptXMvBKunJ1knDkkS+4sYYLA@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> <CAN=4vMpexntEq=hZcmsiXySy-2ptXMvBKunJ1knDkkS+4sYYLA@mail.gmail.com>
On Fri, Jan 12, 2024 at 9:39 PM Roman Perepelitsa
<roman.perepelitsa@xxxxxxxxx> wrote:
>
> 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.
This actually led me to the best (?) solution:
IFS= read -rd '' file_content <file
If IFS is not set, newlines are not stripped. Of course this still
only works if the file does not contain nul bytes, the -d delimiter
has to be something that's not in the file. Roman's sysread approach
doesn't care (and sysread is exactly the thing I forgot that I was
expecting Roman to remind me of, although we both seem to have
forgotten IFS).
For commands,
command | IFS= read -rd '' cmd_stdout
also works, thanks to zsh's fork-to-the-left semantics. This would
not work in other shells.
> # 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
You can speed this up a little by using the -c option to sysread to
get back a count of bytes read, and accumulate that in another var to
avoid having to re-calculate $#content on every loop.
> (( $? == 5 )) || return
> break
> done
> typeset -g REPLY=$content
> }
Messages sorted by:
Reverse Date,
Date,
Thread,
Author