Is there any more efficient way to do the following in zsh?

I imagine that there might be ways to get rid of the intermediate array parameters a and/or b.

The script gets some output from a command. If that output is not empty, it skips the first two lines, then it uses as arguments for another command the text before the first space on each of the remaining lines.

#!/usr/bin/env zsh

packages=$(pip3 list -o)
if [[ -n ${packages} ]]; then
    print "${packages}"
    PYTHONWARNINGS=ignore:DEPRECATION pip3 install -U "${b[@]%% *}"

1 Answer 1

#!/usr/bin/env zsh

packages=(${${(f)"$(pip3 list -o)"}[3,-1]}) || exit

if (($#packages)); then
    print -rl -- $packages
    PYTHONWARNINGS=ignore:DEPRECATION pip3 install -U ${packages%% *}

would be shorter and a bit more zsh-like, but I doubt it would be much faster.

You may want to use pip's --format=freeze to avoid having to strip the header (gives an output in package==1.2.3 format for which you'd need to change the ${packages%% *} to ${packages%==*}).

  • Thanks for the --format=freeze suggestion, but I wanted to print the columns format so I could see both the new & old versions. If I weren't printing that, I'd use freeze.
    – XDR
    Nov 12, 2019 at 18:12
  • What is the point of || exit? Under what circumstances does it change the outcome?
    – XDR
    Nov 12, 2019 at 18:34
  • 1
    @XDR, it exits the script (with pip's exit status) if pip fails. Nov 12, 2019 at 18:36
  • 1
    @XDR, no, it's a matter or taste. I don't like them when not needed as I find it makes the code less legible. Nov 12, 2019 at 19:34
  • 1
    @XDR, in zsh, there's no split+glob upon unquoted parameter expansion, "$array[@]" or "${(@)array}" would preserve the empty elements in $array, but here the array cannot contain empty elements because of the way it's defined (and here you don't want empty elements). Nov 12, 2019 at 19:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .