Re: alternation option end of string

Ray Andrews <[email protected]> Sun, 3 May 2026 17:24:03 -0700
Newsgroups gmane.comp.shells.zsh.devel,gmane.comp.shells.zsh.user
Message-ID <[email protected]>
On 2026-05-03 17:01, Mark J. Reed wrote:
> What you really want is to _remove_ whatever comes after either "cats" 
> or, if the thing after "cat" is not an s, "cat".
>
> But if you're reading comma-separated fields, you can just use `read`:
>
>     IFS=, read base idx comment <<<"$INPUT"
>
>
>    INPUT: file,8a
>     base: file
>      idx: 8a        FAIL
>  comment:
>
>    INPUT: file,a8
>     base: file
>      idx: a8        FAIL
>  comment:
>
>    INPUT: file,a8,comment
>     base: file
>      idx: a8                FAIL
>  comment: comment
>
>    INPUT: file,8a,comment
>     base: file
>      idx: 8a                FAIL
>  comment: comment
>
>    INPUT: file,8a,com,ment
>     base: file
>      idx: 8a                FAIL
>  comment: com,ment

... between commas must be only a number. But I still like the idea, 
because the primary breakdown is indeed by commas (but a comma can occur 
in a comment, which muddies the water somewhat).  Still, I think that 
Roman's method does the job perfectly as it is.  Only a bit more work to 
be sure of the comment.  Here's the whole thing, I wonder if the logic 
can be tightened up even further:

# Tests of s() filename parsing:

function s_split ()
{
     [[ ! "$@" ]] && return # Otherwise it tries to 'run empty' twice.

     # Global so can access at CL:
     s_base=
     s_idx=
     s_comment=
     local remainder=
     local flag_verbose=

[[ "$1" == ',v' ]] && { flag_verbose=1; shift }

     # Strip off the longest match of 'a comma followed by anything' 
from the rear, leaving the basename:
     s_base="${@%%,*}"
     # Mirror image of the above: save whatever was stripped off, this 
will be any combination of idx and comment:
     remainder="${(M)@%%,*}"

     # Roman's power code with back references:
     [[ $remainder == (#b)(,(<->)|,(<->),*) ]] && s_idx=$match[2]$match[3]

     # We found an idx.  Comment will be anything following:
     # If no idx then entire remainder is a commment (strip the comma).
     [[ $s_idx ]] && s_comment="${(S)remainder##,<->,}"\
                  || s_comment="${remainder#,}"

     # Exception! Test: >file,8< : comment leaks thru so kill it:
     [[ ",$s_idx" == "$s_comment" ]] && s_comment=

[[ "$flag_verbose" ]] &&
{
     grnline "\nINPUT: $@"
     echo "base:       $s_base"
     echo "idx:        $s_idx"
     echo "comment:    $s_comment"
}
} # END: s_split()