zsh-users
 help / color / mirror / code / Atom feed
From: Stephane Chazelas <stephane@chazelas.org>
To: "René Neumann" <lists@necoro.eu>
Cc: zsh-users@zsh.org
Subject: Re: [Review Request] Arrays and their usage
Date: Mon, 31 May 2021 18:36:51 +0100	[thread overview]
Message-ID: <20210531173651.2pfklkhv5zizfldg@chazelas.org> (raw)
In-Reply-To: <26fc6ecd-4a05-e562-7274-ba045df536bf@necoro.eu>

2021-05-31 01:24:36 +0200, René Neumann:
[...]
> I always feel a little unsure around arrays in zsh. I've currently used the
> following:
> 
>    local pkgs=( `makepkg --printsrcinfo | \
>                  sed -n -e 's/pkgname = \(.*\)$/\1/p'` )

Here's my take on answering this (repeating some of what has
already been said).

First, I'd say: `...` form of command substitution should really
be banned these days. That's really a broken heritage from the
Bourne shell. There's not good reason to keep using it these
days. The main problem with it is the handling of backslash
inside it (and the awkward nesting and the fact that it's less
legible, etc...).

The sed command could be written:

  sed -n 's/pkgname = //p'

Strictly speaking, it's not exactly equivalent with some sed
implementations when the input contains sequences of bytes that
don't form valid text in the current locale. For instance, in a
locale that uses UTF-8 as its charmap, on the output of:

printf 'foopkgname = bar\200baz\n'

yours would output foobar<LF> while mine would output
foobar<0x80>baz<LF> with GNU sed as the . regexp operator only
matches on *characters* so would not match on that 0x80 byte
which doesn't form a valid character in UTF-8.

Then, leaving `...` (or the better $(...)) unquoted performs
IFS-splitting, so you're left with the same kind of conundrum as
you get in POSIX shells when you leave any form of expansion
($param, $((arith)) as well there!) unquoted though at least
zsh doesn't perform globbing there:

either you're happy that the default value of IFS (space, tab,
newline, nul) is good enough for all splitting, or you need to
set it every time you use it (in zsh, that's for unquoted $(...)
or the $=param operator).

Here, you can do

pkgs=(
  $(
    makepkg --printsrcinfo |
     sed -n 's/pkgname = //p'
  )
)

With the default value of $IFS if you know the values don't
contain any of the $IFS characters. If that can't be guaranteed,
you'd need:

IFS=$'\n'
pkgs=(
  $(
    makepkg --printsrcinfo |
     sed -n 's/pkgname = //p'
  )
)

But in zsh, rather than using IFS-splitting which is cumbersome
to use as it relised on a global parameter, you can use explicit
splitting operators, using the "f" (short for "ps:\n:")
parameter expansion flag. Then you don't have to worry about
what $IFS may contain at the time:

pkgs=(
  ${(f)"$(
    makepkg --printsrcinfo |
     sed -n 's/pkgname = //p'
  )"}
)

Here, we're quoteing the $(...) to disable IFS-splitting and use
the "f" flag to do splitting on line feeds. Note that empty
elements are discarded.

>    pkgs=(${pkgs/#/"$DATABASE/"})

The more idiomatic zsh variant to that ksh syntax would be:

pkgs=( $DATABASE/$^pkgs )

(same as rc's pkgs = ( $DATABASE/$pkgs )).

-- 
Stephane


  parent reply	other threads:[~2021-05-31 17:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-30 23:24 René Neumann
2021-05-31  0:28 ` Mikael Magnusson
2021-05-31  4:24   ` Bart Schaefer
2021-05-31 19:41   ` René Neumann
2021-05-31 17:36 ` Stephane Chazelas [this message]
2021-05-31 20:04   ` René Neumann
2021-05-31 21:42     ` Bart Schaefer
2021-05-31 21:43     ` Lawrence Velázquez
2021-05-31 22:05       ` René Neumann
2021-06-01  5:59     ` Stephane Chazelas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210531173651.2pfklkhv5zizfldg@chazelas.org \
    --to=stephane@chazelas.org \
    --cc=lists@necoro.eu \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).