• Re: Different variable assignments

    From Janis Papanagnou@21:1/5 to Frank Winkler on Sat Oct 12 13:08:48 2024
    On 12.10.2024 09:42, Frank Winkler wrote:
    On 12.10.2024 03:59, Janis Papanagnou wrote:

    It depends on your shell. If you choose Kornshell you won't have that
    issue and can write it as you've done with the output as you'd expect.

    $ uname -a | read var
    $ echo "$var"
    Linux [...snip...]

    The reason is that the last command in a pipeline will (in Kornshell)
    be executed in the "current" shell context.

    Interesting hint! I wasn't aware that there are such differences between
    the shells.

    Yes, it's a subtle difference, but an important one; many shell users
    wondered about the behavior of other shells, and you need to know the
    internal information about subprocesses used in pipes to understand
    why it doesn't work (in other shells), or why it does in ksh.

    And indeed, some simple tests seem to work in an interactive
    ksh.

    You can rely on it with any official ksh (since ksh88) and branches of
    them. (But don't count on it if you're using some inferior ksh clone.)


    Let's see the whole story. For historical reasons, I'm actually using
    ksh for almost all scripts instead of bash for interactive use - not
    knowing about the fact above.

    From your description below I'm not sure you still have a question or
    whether you're just describing what you intended to do and are fine
    with ksh's pipeline behavior. (Specifically I'm unsure about the 'B'
    and what you mean by "sub-command B" in your example(s).)

    If something is still not working for you, please clarify.


    There, I run command A which is producing output and which is calling sub-command B, also producing output. This works fine.
    What I want to achieve is to grab some parts of the output and store it
    in a variable but without changing the output on the screen.

    So I tried something like

    tty=`tty`
    A | tee $tty | ... | read var

    $ man tty
    tty - print the file name of the terminal connected to standard input

    The 'tty' command in your 'tee' pipeline command has no tty attached;
    it reads from the pipe. That's why A | tee $(tty) | ... | read var
    doesn't work as you expected. You have to grab the tty information
    outside the pipeline (as you've experienced).

    Janis


    "tee `tty`" inside the command fails, so I do it outside. The output of
    A is still there but B's is gone (because B doesn't know anything about
    the "tee"?) and the whole thing doesn't seem to be still working. $var
    is empty, though this is a ksh script and the stuff behind "tee" is also working.
    To my understanding, the default B can be changed with an option but
    when I set it to "B | tee $tty", there's still no output.

    AFAIR, "var=`...`" works better but as the primary job is the command
    itself and the variable is just a spin-off product, I'd prefer to do the assignment at the end. I believe it looks better then ;) ...

    Probably it would also be feasible with some temp files but I try to
    avoid them wherever possible.

    Happy week-end!

    fw


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 12 12:01:55 2024
    Il Sat, 12 Oct 2024 13:08:48 +0200, Janis Papanagnou ha scritto:

    (Specifically I'm unsure about the 'B' and what you mean by "sub-command
    B" in your example(s).)

    Waiting for his clarification, I'm thinking that he sees that something
    like:

    $ input=$(tty) && echo 123456789 | tee $input | grep -o 456 | \
    tee $input | read myvar && echo "myvar is $myvar"; input= ; myvar=
    123456789
    456
    myvar is

    doesn't work, while of course:

    $ input=$(tty) && read myvar < <( echo 123456789 | tee $input | \
    grep -o 456 | tee $input ) && echo "myvar is $myvar"; input= ; myvar=
    123456789
    456
    myvar is 456

    does work (BTW: here I'm in Bash).
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to Lem Novantotto on Sat Oct 12 17:57:16 2024
    On 12.10.2024 14:01, Lem Novantotto wrote:

    >Waiting for his clarification, I'm thinking that he sees that something
    >like:
    >
    >$ input=$(tty) && echo 123456789 | tee $input | grep -o 456 | \
    > tee $input | read myvar && echo "myvar is $myvar"; input= ; myvar=
    >123456789
    >456
    >myvar is
    >
    >doesn't work

    I think you're right. But why doesn't it work in ksh?

    > while of course:
    >
    >$ input=$(tty) && read myvar < <( echo 123456789 | tee $input | \
    > grep -o 456 | tee $input ) && echo "myvar is $myvar"; input= ; myvar=
    >123456789
    >456
    >myvar is 456
    >
    >does work (BTW: here I'm in Bash).

    I'm still thinking about the difference between "< <(...)" and "<<< `...`"

    And I would be happy with this one if there was a notation "the other
    way round" ;) ... something like "... >>> $var"

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to Janis Papanagnou on Sat Oct 12 17:49:55 2024
    On 12.10.2024 13:08, Janis Papanagnou wrote:

    >From your description below I'm not sure you still have a question or
    >whether you're just describing what you intended to do and are fine
    >with ksh's pipeline behavior. (Specifically I'm unsure about the 'B'
    >and what you mean by "sub-command B" in your example(s).)

    A spawns B and grabbing the desired information from the common output
    still doesn't work.

    >The 'tty' command in your 'tee' pipeline command has no tty attached;
    >it reads from the pipe. That's why A | tee $(tty) | ... | read var
    >doesn't work as you expected. You have to grab the tty information
    >outside the pipeline (as you've experienced).

    That was also my understanding after the experience ;) ... but thanks
    for confirmation.

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 12 17:09:20 2024
    Il Sat, 12 Oct 2024 17:57:16 +0200, Frank Winkler ha scritto:

    I think you're right. But why doesn't it work in ksh?

    Uhm... It should work. Here it works, at least.

    And sometimes something like that *may* work in bash, too, provided
    we set:
    $ shopt -s lastpipe

    But my command doesn't work instead, in bash. That's why:

    | lastpipe
    | If set, and job control is not active, the shell runs the last command
    | of a pipeline not executed in the background in the current shell
    | environment.
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Frank Winkler on Sat Oct 12 21:32:33 2024
    On Sat, 12 Oct 2024 17:57:16 +0200, Frank Winkler wrote:

    I'm still thinking about the difference between "< <(...)" and "<<<
    `...`"

    Not sure about the extra “<”, but “<(«cmd»)” gets substituted with the
    name of a file (i.e. not stdin) that the process can open and read to get
    the output of «cmd». Similarly “>(«cmd»)” gets substituted with the name
    of a file (i.e. not stdout) that the process can open and write to feed
    input to waiting «cmd».

    “<<” and “<<<”, on the other hand, are for specifying alternative sources
    of inline data for stdin, or you can use “«fd»<<” and “«fd»<<<” to specify
    an alternative «fd» that the process will expect to find already open for reading, to obtain that data.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Sat Oct 12 23:47:34 2024
    On 12.10.2024 23:32, Lawrence D'Oliveiro wrote:
    On Sat, 12 Oct 2024 17:57:16 +0200, Frank Winkler wrote:

    I'm still thinking about the difference between "< <(...)" and "<<<
    `...`"

    Not sure about the extra “<”,

    '<(...)' executes the command indicated by '...' and provides a file descriptor, something like '/dev/fd/5', which (being effectively a
    filename) can be redirected to the 'read' command.

    The shell's 'read' command doesn't read from files but from stdin,
    so if 'read's input is in a file or is the output of a command (as in
    this case) you have to do a redirection; for the first case
    read < file
    and in case of a process substitution (a file named like /dev/fd/5)
    read < <(some command)
    which sort of "expands" to something like
    read < /dev/fd/5

    So it's no "extra" '<', it's just a necessary redirection for a
    command that reads from 'stdin' but not from files.

    Janis

    but “<(«cmd»)” gets substituted with the
    name of a file (i.e. not stdin) that the process can open and read to get
    the output of «cmd». Similarly “>(«cmd»)” gets substituted with the name
    of a file (i.e. not stdout) that the process can open and write to feed
    input to waiting «cmd».

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sat Oct 12 21:50:37 2024
    On Sat, 12 Oct 2024 23:47:34 +0200, Janis Papanagnou wrote:

    '<(...)' executes the command indicated by '...' and provides a file descriptor, something like '/dev/fd/5', which (being effectively a
    filename) can be redirected to the 'read' command.

    It’s an actual file name. The process treats it as just another filename argument. The fact that it encodes a file descriptor is something OS-
    specific, that only code that wants to create such names (like the shell)
    has to worry about.

    The shell's 'read' command doesn't read from files but from stdin

    It can read from any file currently open for reading.

    So it's no "extra" '<' ...

    Ah, I see. Instead of “< <(«cmd›)”, you could have just written “0<(«cmd»)”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Lawrence D'Oliveiro on Sat Oct 12 23:56:33 2024
    On 12.10.2024 23:50, Lawrence D'Oliveiro wrote:
    On Sat, 12 Oct 2024 23:47:34 +0200, Janis Papanagnou wrote:

    '<(...)' executes the command indicated by '...' and provides a file
    descriptor, something like '/dev/fd/5', which (being effectively a
    filename) can be redirected to the 'read' command.

    It’s an actual file name. The process treats it as just another filename argument.

    Exactly. (That's what I was saying.) '/dev/fd/5' acts like a file/path
    name (but only on systems that support /dev/fd mechanism).

    The fact that it encodes a file descriptor is something OS-
    specific, that only code that wants to create such names (like the shell)
    has to worry about.

    The shell's 'read' command doesn't read from files but from stdin

    It can read from any file currently open for reading.

    So it's no "extra" '<' ...

    Ah, I see. Instead of “< <(«cmd›)”, you could have just written “0<(«cmd»)”.

    No.

    (1388)$ read <(cat hello_world)
    ksh: read: /dev/fd/3: invalid variable name
    (1389)$ read < <(cat hello_world)
    (1390)$ echo $REPLY
    Hello world!
    (1391)$ read 0<(cat hello_world)
    ksh: read: /dev/fd/3: invalid variable name

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 12 23:10:06 2024
    Il Sat, 12 Oct 2024 23:07:41 -0000 (UTC), Lem Novantotto ha scritto:

    1) "command2 <<<`command1`": `command2`, equal to the preferable[*] $(command2),

    Sorry:

    1) "command2 <<<`command1`": `command1`, equal to the preferable[*]
    $(command1)
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 12 23:07:41 2024
    Il Sat, 12 Oct 2024 17:57:16 +0200, Frank Winkler ha scritto:

    I'm still thinking about the difference between "< <(...)" and "<<<`...`"

    As already pointed out by Lawrence:

    1) "command2 <<<`command1`": `command2`, equal to the preferable[*] $(command2), can be seen as the output of command2: a string. So with
    <<< you are telling the shell to take this string as input on the
    standard input of command2. So: execute command1, then take its output
    as the input of command2. This is called *command* substitution:
    substitution of a command with its output.

    [*] No characters are special between parenthesis: easier.

    2) "command2 < <(process_of_command1)": here process, which is the
    "active running instance" of command1 - enough: remove the difference,
    think of command1 and stop - is run with its output connected to a
    named FIFO pipe file (or to some file in /dev/fd).
    So <(process_of_command1) is expanded as the name of this file.
    The first < is simple input redirection.
    So: execute command1, connect the output of its process to a special
    file, redirect this special file to input of command2.
    This is called *process* output substitution: substitute a
    process with the name of its output file.
    Process substitution does work only on systems supporting named pipes
    or /dev/fd/... so it's less universal than command substitution.

    Some practical differences. For example, try:

    $ cat <<<$(while true; do echo yes; done)

    Nothing: cat is waiting for the other stuff to end. But it won't end,
    in this case! Gawsh!

    $ cat < <( while true; do echo yes; done)

    Rock'n'roll!

    And I would be happy with this one if there was a notation "the other
    way round" ... something like "... >>> $var"

    You're more the straightforward type of guy, eh! That's fine! ;)
    But, sorry, '>>>' is still to come. In bash, at least. :-)
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 12 23:39:23 2024
    Il Sat, 12 Oct 2024 23:07:41 -0000 (UTC), Lem Novantotto ha scritto:

    As already pointed out by Lawrence:

    And by Janis, of course!
    I apologize.
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to ldo@nz.invalid on Sat Oct 19 10:45:43 2024
    In article <vecmp3$pur$1@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sat, 12 Oct 2024 03:59:49 +0200, Janis Papanagnou wrote:

    ... use bash-specifics like 'coproc' ...

    It isn't bash-specific.

    People on these newsgroups often use phrases like "bash specific" as
    synonyms for "Not strictly POSIX" (*), even though the bash feature under discussion is also found in other shells. In fact, many bash-isms,
    including "coproc", came originally from ksh. I'm sure Janis knows this.

    --
    The key difference between faith and science is that in science, evidence that doesn't fit the theory tends to weaken the theory (that is, make it less likely to
    be believed), whereas in faith, contrary evidence just makes faith stronger (on the assumption that Satan is testing you - trying to make you abandon your faith).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to ldo@nz.invalid on Sat Oct 19 11:45:30 2024
    In article <vec3qb$3q4ms$3@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Fri, 11 Oct 2024 22:50:10 +0200, Frank Winkler wrote:

    ... but it still doesn't solve the issue that I need the result to be
    visible in the parent shell.

    coproc { uname -sr; }
    read -u ${COPROC[0]} var3
    wait $COPROC_PID
    echo $var3

    I'm actually a fan of "coproc" in bash, and I use it in my scripting, but I think it is overkill in most cases. The most general command for variable assignment (in bash) is "mapfile". "mapfile" supercedes "coproc" in most cases. For the possible benefit of OP, here's the standard idiom for using "mapfile", using the "sw_vers" program, which OP mentioned in passing
    (AFAIK, "sw_vers" is a Mac OS thing):

    mapfile -t < <(sw_vers)

    which populates the array MAPFILE.

    A couple of other points:
    1) When using "coproc", you can get away with just $COPROC for the
    output of the co-process. This is a little easier to type than
    ${COPROC[0]} - even if this does get flagged as a warning by the
    "shellcheck" program. Note that in bash, all variables are arrays;
    it's just that most only have one element:
    % bash -c 'echo ${HOME[0]}'
    /home/me
    %

    2) OP's main concern actually seems to be aesthetic. He just wants the
    variable name at the end of the line instead of at the beginning. Kind
    of like the difference between the two styles of assembler languages,
    where some are: "move src,dst" and others (most) are "move dst,src".
    (It's been a long time since I've done assembler language.)

    Finally, note that you just generally learn to avoid the (wrong) idiom of:

    cmd | read bar

    because you learn early on that it doesn't work. I think the most basic
    (works in any sh-like shell, even in the bad old days of Solaris)
    alternative is:

    read bar << EOF
    $(cmd)
    EOF


    -- https://www.rollingstone.com/politics/politics-news/the-10-dumbest-things-ever-said-about-global-warming-200530/

    RS contributor Bill McKibben lambasted this analysis in his 2007 book, Deep Economy.
    It's nice to have microelectronics; it's necessary to have lunch, wrote McKibben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Lem@none.invalid on Sat Oct 19 11:47:16 2024
    In article <veeag0$786f$2@dont-email.me>,
    Lem Novantotto <Lem@none.invalid> wrote:
    ...
    But my command doesn't work instead, in bash. That's why:

    | lastpipe
    | If set, and job control is not active, the shell runs the last command
    | of a pipeline not executed in the background in the current shell
    | environment.

    The key phrase here is "job control is not active". AFAICT, "lastpipe" (bash) works in a script, but not interactively.

    --
    You know politics has really been turned upside down when you have someone in the
    government with a last name of Cheney (Liz, Senator from Wyoming) who is the voice of
    reason.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to janis_papanagnou+ng@hotmail.com on Sat Oct 19 11:50:07 2024
    In article <vecl6n$d0r$1@dont-email.me>,
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    ...
    (In other shells you have to work around the issue as demonstrated in
    other answers to your post. Some workaround are more clumsy some less.

    Setting "lastpipe" works (sort of) in bash.

    A shorter variant of the here-document posted elsethread can be using >here-strings

    $ read var <<< $(uname -a)

    another method is using process substitution and redirection

    $ read var < <(uname -a)

    Both supported by shells like ksh, bash, zsh, but non-standard as are
    some other workaround proposals that use bash-specifics like 'coproc',
    that doesn't work as widely as using '<<<' or '<(...)' do.)

    There are lots of workarounds, but I think the main takeaway is that the obvious-but-wrong idiom of "cmd | read foo" is just TBA.

    --
    Life's big questions are big in the sense that they are momentous. However, contrary to
    appearances, they are not big in the sense of being unanswerable. It is only that the answers
    are generally unpalatable. There is no great mystery, but there is plenty of horror.
    (https://en.wikiquote.org/wiki/David_Benatar)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kenny McCormack on Sat Oct 19 14:52:01 2024
    On 19.10.2024 13:45, Kenny McCormack wrote:
    In article <vec3qb$3q4ms$3@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Fri, 11 Oct 2024 22:50:10 +0200, Frank Winkler wrote:

    ... but it still doesn't solve the issue that I need the result to be
    visible in the parent shell.

    coproc { uname -sr; }
    read -u ${COPROC[0]} var3
    wait $COPROC_PID
    echo $var3

    I'm actually a fan of "coproc" in bash, and I use it in my scripting, but I think it is overkill in most cases. [...]

    Also, if above code is how to use co-processes in Bash, I consider
    that extremely clumsy (if compared to, say, Ksh).

    (Mileages may vary, of course.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kenny McCormack on Sat Oct 19 14:25:14 2024
    On 19.10.2024 12:45, Kenny McCormack wrote:
    In article <vecmp3$pur$1@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sat, 12 Oct 2024 03:59:49 +0200, Janis Papanagnou wrote:

    ... use bash-specifics like 'coproc' ...

    It isn't bash-specific.

    Maybe; I haven't checked all existing shells. I know that the keyword
    is not used in Kornshell. I know it's used in bash. I don't know, e.g.,
    about zsh, the other major shell I'm also interested in.


    People on these newsgroups often use phrases like "bash specific" as
    synonyms for "Not strictly POSIX" (*), even though the bash feature under discussion is also found in other shells. In fact, many bash-isms,
    including "coproc", came originally from ksh. I'm sure Janis knows this.

    Please note that while ksh supports co-processes it doesn't use (to my knowledge) the keyword 'coproc'. - Kornshells co-processes are invoked
    by appending the '|&' token to a command and reads and writes are done
    with 'read -p' and 'print -p', respectively.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Oct 19 12:53:42 2024
    Il Sat, 19 Oct 2024 11:47:16 -0000 (UTC), Kenny McCormack ha scritto:

    AFAICT, "lastpipe" (bash)
    works in a script, but not interactively.

    Uhm... I'm sorry, probably I do not get your point. It's a bash
    shell option: you set it (or unset it), and then you go.

    | $ set -m ; shopt -u lastpipe ; unset my
    | $ echo ciao |read my ; echo $my
    |
    | $ set +m ; shopt -s lastpipe ; unset my
    | $ echo ciao |read my ; echo $my
    | ciao

    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sat Oct 19 21:42:26 2024
    On Sat, 19 Oct 2024 14:52:01 +0200, Janis Papanagnou wrote:

    Also, if above code is how to use co-processes in Bash, I consider that extremely clumsy (if compared to, say, Ksh).

    Bash allows for named coprocs. That means you can have multiple coprocs
    going at once.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to ldo@nz.invalid on Sat Oct 19 22:56:53 2024
    In article <vf1942$1uso$1@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sat, 19 Oct 2024 14:52:01 +0200, Janis Papanagnou wrote:

    Also, if above code is how to use co-processes in Bash, I consider that
    extremely clumsy (if compared to, say, Ksh).

    "extremely" seems more than a bit over the top. Maybe somewhat clumsy, but hardly "extremely".

    Bash allows for named coprocs. That means you can have multiple coprocs
    going at once.

    Yes, but only if you re-compile your own version of bash, with that option turned on in one of the config.h files.

    To be precise, multiple co-procs will seem to work even if not enabled as described above, but things then start to go awry in mysterious ways. I've experienced exactly this until I did the research into how to properly
    enable it.

    But, yes, that's part of the point of making it possible to assign a name
    to a coproc (instead of just taking the default of "coproc").

    --
    If Jeb is Charlie Brown kicking a football-pulled-away, Mitt is a '50s housewife with a black eye who insists to her friends the roast wasn't
    dry.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kenny McCormack on Sun Oct 20 07:09:15 2024
    On 20.10.2024 00:56, Kenny McCormack wrote:
    In article <vf1942$1uso$1@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Sat, 19 Oct 2024 14:52:01 +0200, Janis Papanagnou wrote:

    Also, if above code is how to use co-processes in Bash, I consider that
    extremely clumsy (if compared to, say, Ksh).

    "extremely" seems more than a bit over the top. Maybe somewhat clumsy, but hardly "extremely".

    I don't think it makes much sense to discuss subjective valuations.
    But okay.

    Mine stems from a "per-feature level" (and is no absolute). It was
    based on LDO's suggestion (which was a bit more complex than your
    version) that used; (1) a [new] keyword, (2) command grouping (not
    sure it's necessary[*] in the first place?), (3) using an explicit
    descriptor through (4) a variable, (5) using an array instead of a
    scalar element, and (6) using 'wait' (I'm also not sure this is
    necessary in the first place or just the poster not knowing better?).

    For a simple feature that's really a lot compared to e.g. ksh's way.
    (YMMV. But if "somewhat clumsy" triggers less emotions then I'm fine
    with that.)

    I also think that syntaxes that resemble existing constructs serves "simplicity". Like using '|&', which resembles both, the pipelining communication part '|', and the asynchronicity of the call '&'. It's
    also visible (as already shown elsethread) in the similarity of the
    calling syntax contexts; compare
    uname -sr | read
    versus
    uname -sr |& read -p

    (Yes, '|' is different than '|&', which is more like '&' since it
    separates commands where the pipe connects them. But that was not
    the point here.)

    Of course per bash's defaults even the simple 'uname -sr | read' has
    to be written (for example) as 'uname -sr | { read ; echo $REPLY ;}'
    i.e. with the spurious braces in case you want to access the value,
    so the the added 'coproc { ;}' complexity in Bash might not look too
    bad to Bash users, where Ksh users (like me) will probably value it differently.

    (It's also noteworthy that a common tool like GNU Awk also uses the
    same token for its co-process feature which serves comprehensibility
    and makes it "simple" to use on another "level of consideration".)


    Bash allows for named coprocs. That means you can have multiple coprocs
    going at once.

    Note, that's possible in Ksh as well. Ksh's design decision is that
    the common case (using one co-process) is "extremely" simple to use
    and doesn't add unnecessary complexity or rises questions on details.

    (And using multiple co-processes isn't difficult either with using
    the known shell's redirections concept.)

    [...]

    But, yes, that's part of the point of making it possible to assign a name
    to a coproc (instead of just taking the default of "coproc").


    (Given how [supposedly] rare this feature is used, and that we were
    speaking about subjective impressions, we have to assess that this
    post got far too long. And probably triggers more dispute. Well...)

    Janis

    [*] Would it be possible to write a simplified form like
    'coproc uname -sr;'
    or is it syntactically necessary to write
    'coproc { uname -sr; }'
    ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to All on Tue Oct 15 13:46:42 2024
    On 12.10.2024 17:57, I wrote:

    >I think you're right. But why doesn't it work in ksh?

    BTW: in an interactive ksh, the example does work:

    $ input=$(tty) && echo 123456789 | tee $input | grep -o 456 | tee $input
    | read myvar && echo "myvar is $myvar"; input= ; myvar=
    123456789
    456
    myvar is 456
    $

    And it also does when I put this into a ksh script.

    The thing in question does

    tty=`tty`
    sudo openconnect -b ... |\
    tee $tty | grep "^Session authentication will expire at" |\
    cut -d ' ' -f 7- | read end

    and this completely fails. Terminal output is missing, $end is empty and
    the whole command doesn't seem to work. Without the last two lines, it's working perfectly.
    "sudo" also doesn't seem to be the problem as simple tests are working.

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to All on Thu Oct 24 11:30:34 2024
    On 15.10.2024 13:46, I wrote:

    >The thing in question does
    >
    >tty=`tty`
    >sudo openconnect -b ... |\
    >   tee $tty | grep "^Session authentication will expire at" |\
    >   cut -d ' ' -f 7- | read end
    >
    >and this completely fails. Terminal output is missing, $end is empty and
    >the whole command doesn't seem to work. Without the last two lines, it's
    >working perfectly.
    >"sudo" also doesn't seem to be the problem as simple tests are working.

    After some more testing with just a "tee" into a file, it looks like the
    pipe starts OC and writes its output (including the part I want to
    "grep" in to the file but then hangs. Everything following this line in
    the script doesn't seem to be done, anyway. Maybe some effect of the
    background option?

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to usenet@f.winkler-ka.de on Thu Oct 24 11:21:27 2024
    In article <lnuidqFk4dU1@mid.individual.net>,
    Frank Winkler <usenet@f.winkler-ka.de> wrote:
    On 15.10.2024 13:46, I wrote:

    The thing in question does

    tty=`tty`
    sudo openconnect -b ... |\
    tee $tty | grep "^Session authentication will expire at" |\
    cut -d ' ' -f 7- | read end

    and this completely fails. Terminal output is missing, $end is empty and
    the whole command doesn't seem to work. Without the last two lines, it's
    working perfectly.
    "sudo" also doesn't seem to be the problem as simple tests are working.


    OK, let's try to normalize this. But first, please tell which shell you
    are targeting. I.e., how much old-compatibility do you need?

    I'm going to assume bash, but there isn't much difference. In particular,
    note that $() is POSIX, so you really don't need to ever mess with ``.

    Also note: You do not need \ at the end of the line if the line ends with | (also true for lines that end with || or && - and possibly others)

    Anyway, this should do it:

    tty=$(tty)
    end="$(sudo openconnect -b ... |
    tee $tty | grep "^Session authentication will expire at" |
    cut -d ' ' -f 7-)"

    Note also that the grep and the cut could be merged into a single
    invocation of awk - but I don't know enough about what you're doing to be
    more specific. You can probably also eliminate all of the "tty" stuff by writing either to /dev/tty (which is generic Unix) or /dev/stderr (which
    might be Linux-specific). Also, if you use gawk (GNU awk), then you can
    write to /dev/stderr from within AWK and eliminate all of the "tee" stuff
    as well.

    --
    "Remember when teachers, public employees, Planned Parenthood, NPR and PBS crashed the stock market, wiped out half of our 401Ks, took trillions in
    TARP money, spilled oil in the Gulf of Mexico, gave themselves billions in bonuses, and paid no taxes? Yeah, me neither."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to Kenny McCormack on Thu Oct 24 23:43:59 2024
    On 24.10.2024 13:21, Kenny McCormack wrote:

    >I'm going to assume bash, but there isn't much difference. In
    particular,
    >note that $() is POSIX, so you really don't need to ever mess with ``.

    I know that "$()" is POSIX but I don't feel "``" as a mess but in fact,
    I like it much better. And we're talking about ksh.

    >Also note: You do not need \ at the end of the line if the line ends
    with |
    >(also true for lines that end with || or && - and possibly others)
    >
    >Anyway, this should do it:
    >
    > tty=$(tty)
    > end="$(sudo openconnect -b ... |
    > tee $tty | grep "^Session authentication will expire at" |
    > cut -d ' ' -f 7-)"

    I also know that the "``" thing should and does do it but I explicitly
    asked why the "read" approach fails and that I'd prefer a solution with
    the assignment at the end.

    You're absolutely right that there's probably a more elgant and cooler
    way instead of "grep" and "cut" (maybe with "awk") but that was a quick
    one and the details can be optimized when things are working. But thanks
    for the ideas.

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Thu Oct 24 22:45:39 2024
    Il Thu, 24 Oct 2024 11:30:34 +0200, Frank Winkler ha scritto:

    Maybe some effect of the background option?

    I guess it could be so.

    However, since I don't use openconnect I could only try something like:

    | $ openconnect -b unresponsive:local:ip:address | tee | grep .
    | POST https://192.168.38.38/
    | Failed to connect to host 192.168.38.38
    | Failed to open HTTPS connection to 192.168.38.38
    | Failed to complete authentication
    | Failed to connect to 192.168.38.38:443: Nessun instradamento per l'host

    which works, and in bash gives me the stderr printed by openconnect - the
    three lines in the middle - and the stdout (piped from openconnect to tee
    and then from tee to grep) printed in red by grep - first and last line).
    In ksh no red color, but it works the same.

    Then, in standard bash:

    |$ openconnect -b 192.168.38.38 2>&1 | tee | grep -o POST |read end ; \
    echo $end
    |

    whilst in ksh:

    |$ openconnect -b 192.168.38.38 2>&1 | tee | grep -o POST |read end ; \
    echo $end
    POST

    Again, it works as expected. So I didn't come to anything useful. Sorry.
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Frank Winkler on Fri Oct 25 06:57:12 2024
    On 24.10.2024 23:43, Frank Winkler wrote:
    On 24.10.2024 13:21, Kenny McCormack wrote:

    I'm going to assume bash, but there isn't much difference. In
    particular,
    note that $() is POSIX, so you really don't need to ever mess with ``.

    I know that "$()" is POSIX but I don't feel "``" as a mess but in fact,
    I like it much better. And we're talking about ksh.

    [...]

    I also know that the "``" thing should and does do it but I explicitly
    asked why the "read" approach fails and that I'd prefer a solution with
    the assignment at the end.

    The posts have indicated that folks here were trying to clarify
    what you [intended to] do. Kenny was suggesting some basic things
    that you should indeed consider adapting to make your programs
    clearer and less error-prone. Of course you can do what you like.
    But you should really consider the "new" (i.e. 1988) syntax for
    command substitution that Ksh had invented for documented reasons.

    Janis

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Lem@none.invalid on Fri Oct 25 07:10:35 2024
    In article <vfeimj$2qggf$3@dont-email.me>,
    Lem Novantotto <Lem@none.invalid> wrote:
    ...
    | $ openconnect -b unresponsive:local:ip:address | tee | grep .

    Note that "tee" when run with no args is a no-op.
    It is, in fact, equivalent to running "cat" (with no args).

    --
    I am not a troll.
    Rick C. Hodgin
    I am not a crook.
    Rick M. Nixon

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Fri Oct 25 08:57:29 2024
    Il Fri, 25 Oct 2024 07:10:35 -0000 (UTC), Kenny McCormack ha scritto:

    Note that "tee" when run with no args is a no-op.

    Of course. :)
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to All on Fri Oct 11 20:11:57 2024
    Hi there !

    Consider the following commands:


    $ var1=`uname -sr`
    $ echo $var1
    Darwin 24.0.0
    $ read var2 <<< `uname -sr`
    $ echo $var2
    Darwin 24.0.0
    $ uname -sr | read var3
    $ echo $var3

    $ uname -sr | read -p var3
    $ echo $var3

    $

    While the first two ones behave like expected, I wonder why the latter
    ones fail. What's the difference behind the scenes?

    And even more confusing, why does this familiar one work anyway?

    $ sw_vers | while read line; do echo $line; done
    ProductName: macOS
    ProductVersion: 15.0.1
    BuildVersion: 24A348
    $

    I've been using commands like that one for a very long time and that's
    why I tried the simple "read" above - with no success.

    How can I do such an assignment at the end of a command instead of the beginning? Any ideas?

    TIA

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to All on Fri Oct 11 19:56:03 2024
    Hi there !

    Consider the following commands:


    $ var1=`uname -sr`
    $ echo $var1
    Darwin 24.0.0
    $ read var2 <<< `uname -sr`
    $ echo $var2
    Darwin 24.0.0
    $ uname -sr | read var3
    $ echo $var3

    $ uname -sr | read -p var3
    $ echo $var3

    $

    While the first two ones behave like expected, I wonder why the latter
    ones fail. What's the difference behind the scenes? How can I do such an assignment at the end of a command instead of the beginning? Any ideas?

    TIA

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John-Paul Stewart@21:1/5 to Frank Winkler on Fri Oct 11 14:27:40 2024
    On 2024-10-11 2:11 p.m., Frank Winkler wrote:
    Hi there !

    Consider the following commands:


    $ var1=`uname -sr`
    $ echo $var1
    Darwin 24.0.0
    $ read var2 <<< `uname -sr`
    $ echo $var2
    Darwin 24.0.0
    $ uname -sr | read var3
    $ echo $var3

    $ uname -sr | read -p var3
    $ echo $var3

    $

    While the first two ones behave like expected, I wonder why the latter
    ones fail. What's the difference behind the scenes?

    I don't know about other shells, but in Bash each command in a pipeline
    is run in a subshell. (See the "Pipelines" section of the Bash man
    page.) Thus you're doing the 'read var3' part in a different shell than
    where 'echo $var3' runs. That's why it is empty when you echo it.

    And even more confusing, why does this familiar one work anyway?

    $ sw_vers | while read line; do echo $line; done
    ProductName: macOS
    ProductVersion: 15.0.1
    BuildVersion: 24A348

    Here the subshell runs everything between 'while' and 'done' so the read
    and echo commands are in the same (sub)shell this time.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to John-Paul Stewart on Fri Oct 11 20:45:07 2024
    On 11.10.2024 20:27, John-Paul Stewart wrote:

    >I don't know about other shells, but in Bash each command in a pipeline
    >is run in a subshell. (See the "Pipelines" section of the Bash man
    >page.) Thus you're doing the 'read var3' part in a different shell than
    >where 'echo $var3' runs. That's why it is empty when you echo it.

    That sounds very plausible - thanks for enlighting! :)
    So this is not a "read" issue but rather a matter of shell instance and
    hence there's no way to do the assignment at the end?

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Helmut Waitzmann@21:1/5 to All on Fri Oct 11 22:20:26 2024
    Frank Winkler <usenet@f.winkler-ka.de>:
    Hi there !


    Consider the following commands:



    $ var1=`uname -sr`
    $ echo $var1
    Darwin 24.0.0
    $ read var2 <<< `uname -sr`
    $ echo $var2
    Darwin 24.0.0
    $ uname -sr | read var3
    $ echo $var3

    $ uname -sr | read -p var3
    $ echo $var3

    $

    While the first two ones behave like expected, I wonder why the
    latter ones fail. What's the difference behind the scenes?


    And even more confusing, why does this familiar one work anyway?


    $ sw_vers | while read line; do echo $line; done
    ProductName: macOS
    ProductVersion: 15.0.1
    BuildVersion: 24A348
    $

    I've been using commands like that one for a very long time and
    that's why I tried the simple "read" above - with no success.


    How can I do such an assignment at the end of a command instead
    of the beginning? Any ideas?


    uname -sr | { read var3 ; echo $var3 ; }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Frank Winkler on Fri Oct 11 21:03:07 2024
    On Fri, 11 Oct 2024 22:50:10 +0200, Frank Winkler wrote:

    ... but it still doesn't solve the issue that I need the result to be
    visible in the parent shell.

    coproc { uname -sr; }
    read -u ${COPROC[0]} var3
    wait $COPROC_PID
    echo $var3

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to Helmut Waitzmann on Fri Oct 11 22:50:10 2024
    On 11.10.2024 22:20, Helmut Waitzmann wrote:

    > uname -sr | { read var3 ; echo $var3 ; }

    That's exactly how I just wanted to confirm John-Paul's answer ...

    $ uname -sr | ( read var3; echo $var3 )
    Darwin 24.0.0
    $

    ... but it still doesn't solve the issue that I need the result to be
    visible in the parent shell.

    Regards

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Weisgerber@21:1/5 to Frank Winkler on Fri Oct 11 23:25:39 2024
    On 2024-10-11, Frank Winkler <usenet@f.winkler-ka.de> wrote:

    $ uname -sr | ( read var3; echo $var3 )
    Darwin 24.0.0
    $

    ... but it still doesn't solve the issue that I need the result to be
    visible in the parent shell.

    read var3 <<EOF
    $(uname -sr)
    EOF
    echo "$var3"

    --
    Christian "naddy" Weisgerber naddy@mips.inka.de

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Frank Winkler on Sat Oct 12 03:59:49 2024
    On 11.10.2024 20:45, Frank Winkler wrote:
    On 11.10.2024 20:27, John-Paul Stewart wrote:

    I don't know about other shells, but in Bash each command in a pipeline
    is run in a subshell. (See the "Pipelines" section of the Bash man
    page.) Thus you're doing the 'read var3' part in a different shell than
    where 'echo $var3' runs. That's why it is empty when you echo it.

    That sounds very plausible - thanks for enlighting! :)

    So this is not a "read" issue but rather a matter of shell instance and
    hence there's no way to do the assignment at the end?

    It depends on your shell. If you choose Kornshell you won't have that
    issue and can write it as you've done with the output as you'd expect.

    $ uname -a | read var
    $ echo "$var"
    Linux [...snip...]

    The reason is that the last command in a pipeline will (in Kornshell)
    be executed in the "current" shell context.

    (In other shells you have to work around the issue as demonstrated in
    other answers to your post. Some workaround are more clumsy some less.
    A shorter variant of the here-document posted elsethread can be using here-strings

    $ read var <<< $(uname -a)

    another method is using process substitution and redirection

    $ read var < <(uname -a)

    Both supported by shells like ksh, bash, zsh, but non-standard as are
    some other workaround proposals that use bash-specifics like 'coproc',
    that doesn't work as widely as using '<<<' or '<(...)' do.)

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Janis Papanagnou on Sat Oct 12 02:26:44 2024
    On Sat, 12 Oct 2024 03:59:49 +0200, Janis Papanagnou wrote:

    ... use bash-specifics like 'coproc' ...

    It isn’t bash-specific.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Winkler@21:1/5 to Janis Papanagnou on Sat Oct 12 09:42:22 2024
    On 12.10.2024 03:59, Janis Papanagnou wrote:

    >It depends on your shell. If you choose Kornshell you won't have that
    >issue and can write it as you've done with the output as you'd expect.
    >
    >$ uname -a | read var
    >$ echo "$var"
    >Linux [...snip...]
    >
    >The reason is that the last command in a pipeline will (in Kornshell)
    >be executed in the "current" shell context.

    Interesting hint! I wasn't aware that there are such differences between
    the shells. And indeed, some simple tests seem to work in an interactive
    ksh.

    Let's see the whole story. For historical reasons, I'm actually using
    ksh for almost all scripts instead of bash for interactive use - not
    knowing about the fact above.

    There, I run command A which is producing output and which is calling sub-command B, also producing output. This works fine.
    What I want to achieve is to grab some parts of the output and store it
    in a variable but without changing the output on the screen.

    So I tried something like

    tty=`tty`
    A | tee $tty | ... | read var

    "tee `tty`" inside the command fails, so I do it outside. The output of
    A is still there but B's is gone (because B doesn't know anything about
    the "tee"?) and the whole thing doesn't seem to be still working. $var
    is empty, though this is a ksh script and the stuff behind "tee" is also working.
    To my understanding, the default B can be changed with an option but
    when I set it to "B | tee $tty", there's still no output.

    AFAIR, "var=`...`" works better but as the primary job is the command
    itself and the variable is just a spin-off product, I'd prefer to do the assignment at the end. I believe it looks better then ;) ...

    Probably it would also be feasible with some temp files but I try to
    avoid them wherever possible.

    Happy week-end!

    fw

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Frank Winkler on Sat Oct 12 07:51:47 2024
    On Sat, 12 Oct 2024 09:42:22 +0200, Frank Winkler wrote:

    AFAIR, "var=`...`" works ...

    POSIX also allows

    $(«cmd»)

    as a nicer alternative to

    `«cmd»`

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to oe.throttle@xoxy.net on Fri Nov 15 10:58:37 2024
    In article <83y12u2xyt.fsf@helmutwaitzmann.news.arcor.de>,
    Helmut Waitzmann <oe.throttle@xoxy.net> wrote:
    ...

    uname -sr | { read var3 ; echo $var3 ; }


    More simply;

    uname -sr

    --
    If Jeb is Charlie Brown kicking a football-pulled-away, Mitt is a '50s housewife with a black eye who insists to her friends the roast wasn't
    dry.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lem Novantotto@21:1/5 to All on Sat Nov 16 00:07:54 2024
    Il Fri, 15 Nov 2024 10:58:37 -0000 (UTC), Kenny McCormack ha scritto:

    In article <83y12u2xyt.fsf@helmutwaitzmann.news.arcor.de>,
    Helmut Waitzmann <oe.throttle@xoxy.net> wrote:
    ...

    uname -sr | { read var3 ; echo $var3 ; }


    More simply;

    uname -sr

    LOL!
    That was funny, thanks. :-D
    --
    Bye, Lem

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)