• random case construct in ksh

    From Laurens =?ISO-8859-1?Q?Kils=2DH=FCt@21:1/5 to All on Sat Aug 6 17:09:22 2022
    In bash I have used a construct like the following to pick from a
    number of cases at random. How would I do the same thing in ksh?

    ```bash

    case $(($RANDOM%3)) in

    0) echo "case 1" ;;

    1) echo "case 2" ;;

    2) echo "case 3" ;;

    esac

    ```

    thanks,

    lkh

    --
    Laurens Kils-H�tten
    https://sdf-eu.org/~lkh

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to All on Sat Aug 6 20:13:27 2022
    On 06.08.2022 19:09, Laurens Kils-H�tten wrote:
    In bash I have used a construct like the following to pick from a
    number of cases at random. How would I do the same thing in ksh?

    The case construct is standard and works in all POSIX shells
    as it is. In ksh, therefore, you can write it the same way.
    The only thing you probably cannot rely on in POSIX shells is
    the RANDOM variable (which ksh of course supports).

    For readability I prefer the [non-standard] $(( RANDOM % 3 ))
    and I also write the tags (as the standard allows) in symmetric
    parentheses like: (2) echo ... ;;

    Janis


    ```bash

    case $(($RANDOM%3)) in

    0) echo "case 1" ;;

    1) echo "case 2" ;;

    2) echo "case 3" ;;

    esac

    ```

    thanks,

    lkh


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Laurens =?ISO-8859-1?Q?Kils=2DH=FCt@21:1/5 to Janis Papanagnou on Mon Aug 8 06:30:46 2022
    Janis Papanagnou <[email protected]> wrote:
    The only thing you probably cannot rely on in POSIX shells is
    the RANDOM variable (which ksh of course supports).

    Yes, that was precisely the problem. Also, I learned that /bin/sh and
    /bin/ksh are not the same on netbsd ;-)

    In /bin/sh this works:

    #/bin/sh

    case $(( $$ %3)) in

    0) echo "case 1" ;;

    1) echo "case 2" ;;

    2) echo "case 3" ;;

    esac

    --
    Have this adventurer for your next game:
    Rosalie is a farmer
    STR 14 INT 10 WIS 9 DEX 9 CON 10 CHA 11
    HP 5 90 gp

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to All on Mon Aug 8 12:34:02 2022
    On 08.08.2022 08:30, Laurens Kils-H�tten wrote:
    Janis Papanagnou <[email protected]> wrote:
    The only thing you probably cannot rely on in POSIX shells is
    the RANDOM variable (which ksh of course supports).

    Yes, that was precisely the problem. Also, I learned that /bin/sh and /bin/ksh are not the same on netbsd ;-)

    But ksh is a (extreme) superset of sh, so you shouldn't have issues
    as long as you program in POSIX or if you define ksh (or bash, etc.)
    in the first place, if you want to use some of the modern features.

    On legacy systems /bin/sh might be old bourne shell, but typically
    you have a POSIX shell defined as /bin/sh nowadays. Other shells
    may lie behind the somewhat generic "sh"; shells like ksh or bash
    can often be found, but also other shells that (basically) conform
    to POSIX. It is quite safe to assume any POSIX shell behind /bin/sh.


    In /bin/sh this works:

    I don't see why that shouldn't work in other POSIX shells as well;
    try it with ksh, bash, zsh, etc.

    Unless you want to write widely portable (POSIX) scripts use the one
    that serves best or that is available in your system environments.
    And the powerful modern shells (ksh, bash, zsh) support a common base
    of extended features; feel free to use them if you are not restricted
    by other rules or requirements.

    Janis


    #/bin/sh

    case $(( $$ %3)) in

    0) echo "case 1" ;;

    1) echo "case 2" ;;

    2) echo "case 3" ;;

    esac


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Geoff Clare@21:1/5 to All on Mon Aug 8 13:59:50 2022
    Laurens Kils-Hütten wrote:

    In /bin/sh this works:

    #/bin/sh

    case $(( $$ %3)) in

    0) echo "case 1" ;;

    1) echo "case 2" ;;

    2) echo "case 3" ;;

    esac

    In your original post you said you wanted to choose "at random".
    Using $(($$%3)) is very much not random:

    $ for i in {1..10}; do sh -c 'echo $(($$%3))'; done
    1
    2
    0
    1
    2
    0
    1
    2
    0
    1

    (on almost all systems -- I believe there are some that randomise
    PID allocation).

    --
    Geoff Clare <[email protected]>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to [email protected] on Mon Aug 8 15:05:54 2022
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    In your original post you said you wanted to choose "at random".
    Using $(($$%3)) is very much not random:

    Leaving aside the philosophical question of whether any number generated by software is truly random (i.e., anything short of attaching a Geiger
    counter to your PC), using $$ as a sort-of-random-number in a shell script
    is a fairly common, although flawed, practice.

    Modern shells (e.g., bash) have RANDOM as a way of getting actual (subject,
    of course, to the caveats mentioned above) random number in a shell script.
    I don't know what other shells have RANDOM.

    Anyway, I found the original thread topic confusing, so I changed it.

    --
    I'm building a wall.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Laurens =?ISO-8859-1?Q?Kils=2DH=FCt@21:1/5 to Janis Papanagnou on Mon Aug 8 17:55:16 2022
    Janis Papanagnou <[email protected]> wrote:
    On 08.08.2022 12:34, Janis Papanagnou wrote:
    On 08.08.2022 08:30, Laurens Kils-H�tten wrote:
    Janis Papanagnou <[email protected]> wrote:
    The only thing you probably cannot rely on in POSIX shells is
    the RANDOM variable (which ksh of course supports).

    [...]

    In /bin/sh this works:

    I don't see why that shouldn't work in other POSIX shells as well;
    try it with ksh, bash, zsh, etc.

    $$ seems to be the only construct supported by netbsd's /bin/sh, so that's
    what I'll use. Pseudo-randomness is enough for my use case.

    Unless you want to write widely portable (POSIX) scripts use the one
    that serves best or that is available in your system environments.

    Exactly, the point is portability (and also to learn about the different shells).

    Thanks!

    lkh

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Janis Papanagnou on Mon Aug 8 19:28:49 2022
    On 08.08.2022 12:34, Janis Papanagnou wrote:
    On 08.08.2022 08:30, Laurens Kils-H�tten wrote:
    Janis Papanagnou <[email protected]> wrote:
    The only thing you probably cannot rely on in POSIX shells is
    the RANDOM variable (which ksh of course supports).

    [...]

    In /bin/sh this works:

    I don't see why that shouldn't work in other POSIX shells as well;
    try it with ksh, bash, zsh, etc.

    Unless you want to write widely portable (POSIX) scripts use the one
    that serves best or that is available in your system environments.
    And the powerful modern shells (ksh, bash, zsh) support a common base
    of extended features; feel free to use them if you are not restricted
    by other rules or requirements.

    Janis


    #/bin/sh

    case $(( $$ %3)) in

    I spoke about availability of RANDOM in modern powerful shells
    (like ksh, bash, zsh) as opposed to the POSIX standard. Others
    pointed out already about the non-randomness of $$.

    In case you cannot or don't want to use one of these shells,
    which are the simplest access to some randomness, there's also
    the Unix operating system that _may_ support random data; check
    whether you have /dev/urandom available to get random data.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Laurens =?ISO-8859-1?Q?Kils=2DH=FCt@21:1/5 to Kenny McCormack on Mon Aug 8 18:02:08 2022
    Kenny McCormack <[email protected]> wrote:
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    In your original post you said you wanted to choose "at random".
    Using $(($$%3)) is very much not random:

    Leaving aside the philosophical question of whether any number generated by software is truly random (i.e., anything short of attaching a Geiger
    counter to your PC), using $$ as a sort-of-random-number in a shell script
    is a fairly common, although flawed, practice.

    Modern shells (e.g., bash) have RANDOM as a way of getting actual (subject, of course, to the caveats mentioned above) random number in a shell script.
    I don't know what other shells have RANDOM.

    I see, turns out that netbsd's /bin/sh doesn't support RANDOM, yet. So $$
    seems to be the only portable option. Sort-of-randomness is enough for
    my use case.


    Anyway, I found the original thread topic confusing, so I changed it.

    it reflected my state of mind, I guess ;D

    --
    Have this adventurer for your next game:
    Peter dreams of riding a dragon ?
    STR 12 INT 8 WIS 10 DEX 6 CON 11 CHA 11
    HP 3 110 gp

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Weisgerber@21:1/5 to Kenny McCormack on Mon Aug 8 17:00:18 2022
    On 2022-08-08, Kenny McCormack <[email protected]> wrote:

    Modern shells (e.g., bash) have RANDOM as a way of getting actual (subject, of course, to the caveats mentioned above) random number in a shell script.
    I don't know what other shells have RANDOM.

    Well, it's a ksh88 feature.

    --
    Christian "naddy" Weisgerber [email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Laurens Kils-Htten on Mon Aug 8 18:37:46 2022
    In article <tcrj30$1clb$[email protected]>,
    Laurens Kils-Htten <[email protected]> wrote:
    Kenny McCormack <[email protected]> wrote:
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    In your original post you said you wanted to choose "at random".
    Using $(($$%3)) is very much not random:

    Leaving aside the philosophical question of whether any number generated by >> software is truly random (i.e., anything short of attaching a Geiger
    counter to your PC), using $$ as a sort-of-random-number in a shell script >> is a fairly common, although flawed, practice.

    Modern shells (e.g., bash) have RANDOM as a way of getting actual (subject, >> of course, to the caveats mentioned above) random number in a shell script. >> I don't know what other shells have RANDOM.

    I see, turns out that netbsd's /bin/sh doesn't support RANDOM, yet.

    Nor does "dash" on Debian systems.
    Interestingly enough, busybox's sh does have RANDOM.

    So $$ seems to be the only portable option. Sort-of-randomness is enough
    for my use case.

    I suppose if portabilty is the main concern, then using something like /dev/urandom would be right out...

    Anyway, I found the original thread topic confusing, so I changed it.

    it reflected my state of mind, I guess ;D

    Quite so.

    --
    The randomly chosen signature file that would have appeared here is more than 4 lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/TedCruz

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Martijn Dekker on Tue Aug 9 11:37:37 2022
    On 09.08.2022 11:32, Martijn Dekker wrote:
    Op 06-08-22 om 19:13 schreef Janis Papanagnou:
    For readability I prefer the [non-standard] $(( RANDOM % 3 ))

    FYI, referring to variables without a leading $ in arithmetic
    expressions is perfectly standard:

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04

    | If the shell variable x contains a value that forms a valid integer
    | constant, optionally including a leading <plus-sign> or <hyphen-
    | minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall
    | return the same value.

    Oh, thanks! - Has that changed? (I seem to recall that last time I
    looked at that issue it didn't support $-less variables in arithmetic expressions.) - Anyway, good to know.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martijn Dekker@21:1/5 to All on Tue Aug 9 10:32:07 2022
    Op 06-08-22 om 19:13 schreef Janis Papanagnou:
    For readability I prefer the [non-standard] $(( RANDOM % 3 ))

    FYI, referring to variables without a leading $ in arithmetic
    expressions is perfectly standard:

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04
    | If the shell variable x contains a value that forms a valid integer
    | constant, optionally including a leading <plus-sign> or <hyphen-
    | minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall
    | return the same value.

    --
    || modernish -- harness the shell
    || https://github.com/modernish/modernish
    ||
    || KornShell lives!
    || https://github.com/ksh93/ksh

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Geoff Clare@21:1/5 to All on Tue Aug 9 13:37:32 2022
    Laurens Kils-Hütten wrote:

    I see, turns out that netbsd's /bin/sh doesn't support RANDOM, yet. So $$ seems to be the only portable option. Sort-of-randomness is enough for
    my use case.

    If you don't need a pure shell solution, you can do better by using
    the rand() function in awk. If you seed it with $$, it will produce a
    much more random looking sequence than $$ alone.

    Something like:

    case $(awk "BEGIN { srand($$); print int(3*rand()); }" /dev/null) in
    ...
    esac

    --
    Geoff Clare <[email protected]>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Geoff Clare@21:1/5 to Janis Papanagnou on Tue Aug 9 13:25:31 2022
    Janis Papanagnou wrote:

    On 09.08.2022 11:32, Martijn Dekker wrote:

    FYI, referring to variables without a leading $ in arithmetic
    expressions is perfectly standard:

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04

    | If the shell variable x contains a value that forms a valid integer
    | constant, optionally including a leading <plus-sign> or <hyphen-
    | minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall
    | return the same value.

    Oh, thanks! - Has that changed? (I seem to recall that last time I
    looked at that issue it didn't support $-less variables in arithmetic expressions.) - Anyway, good to know.

    It was a common misconception in the early days, and the standard was
    changed to clarify it at some point. However, _assigning_ to variables
    was always clearly required to be supported, and the value of an
    assignment operation is the new value of the assigned variable, so
    it made no sense to interpret the standard as requiring:

    echo $((x=42))

    to output 42, but not requiring:

    x=42; echo $((x))

    to output 42.

    --
    Geoff Clare <[email protected]>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Helmut Waitzmann@21:1/5 to All on Tue Aug 9 19:09:54 2022
    Janis Papanagnou <[email protected]>:
    On 09.08.2022 11:32, Martijn Dekker wrote:
    Op 06-08-22 om 19:13 schreef Janis Papanagnou:
    For readability I prefer the [non-standard] $(( RANDOM % 3 ))

    FYI, referring to variables without a leading $ in arithmetic
    expressions is perfectly standard:

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04

    | If the shell variable x contains a value that forms a valid integer
    | constant, optionally including a leading <plus-sign> or <hyphen-
    | minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall
    | return the same value.

    Oh, thanks! - Has that changed? (I seem to recall that last time I
    looked at that issue it didn't support $-less variables in arithmetic >expressions.) - Anyway, good to know.

    There might be a difference, though, if the value of the variable is
    not a literal integer, but a string resembling an integer
    expression.  Try, using different shells, the following commands:

    v='6*7'
    printf '%s\n' "$((v))"
    printf '%s\n' "$((${v}))"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Helmut Waitzmann on Wed Aug 10 10:45:28 2022
    On 09.08.2022 19:09, Helmut Waitzmann wrote:
    Janis Papanagnou <[email protected]>:
    On 09.08.2022 11:32, Martijn Dekker wrote:
    Op 06-08-22 om 19:13 schreef Janis Papanagnou:
    For readability I prefer the [non-standard] $(( RANDOM % 3 ))

    FYI, referring to variables without a leading $ in arithmetic
    expressions is perfectly standard:

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04


    | If the shell variable x contains a value that forms a valid integer
    | constant, optionally including a leading <plus-sign> or <hyphen-
    | minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall
    | return the same value.

    Oh, thanks! - Has that changed? (I seem to recall that last time I
    looked at that issue it didn't support $-less variables in arithmetic
    expressions.) - Anyway, good to know.

    There might be a difference, though, if the value of the variable is not
    a literal integer, but a string resembling an integer expression. Try,
    using different shells, the following commands:

    v='6*7'
    printf '%s\n' "$((v))"
    printf '%s\n' "$((${v}))"

    I anyway wouldn't have expected that formulas in string variables
    would have been handled (like ksh/bash/zsh do) in the first place.

    A probably more interesting case (where these three shells differ)
    is
    printf '%s\n' $(("${v}"))


    Janis

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