From a232ab562423eccb9523c190c5e03242320cc3fd Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 30 Oct 2007 14:01:32 +0000 Subject: users/12149: "@" with splitting in double quotes retains empty fields --- ChangeLog | 6 ++++++ Doc/Zsh/expn.yo | 11 +++++++++++ Src/subst.c | 23 +++++++++++++---------- Test/D04parameter.ztst | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf9096faa..757821aff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-10-30 Peter Stephenson + + * users/12149: Doc/Zsh/expn.yo, Src/subst.c, + Test/D04parameter.ztst: "${(@s.:.)...}" retains empty + fields, although "${(s.:.)...}" remains backward compatible. + 2007-10-30 Peter Stephenson * 24030, adapted: Src/Modules/curses.c: turning off a key timeout diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index cc87ebe6f..f48616580 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -960,6 +960,17 @@ separator var(string). Note that a var(string) of two or more characters means that all of them must match in sequence; this differs from the treatment of two or more characters in the tt(IFS) parameter. See also the tt(=) flag and the tt(SH_WORD_SPLIT) option. + +For historical reasons, the usual behaviour that empty array elements +are retained inside double quotes is disabled for arrays generated +by splitting; hence the following: + +example(line="one::three" +print -l "${(s.:.)line}") + +produces two lines of output for tt(one) and tt(three) and elides the +empty field. To override this behaviour, supply the "(@)" flag as well, +i.e. tt("${(@s.:.)line}"). ) enditem() diff --git a/Src/subst.c b/Src/subst.c index 6ce723acd..e586ede9a 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1260,13 +1260,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * parameter (the value v) to storing them in val and aval. * However, sometimes you find v reappearing temporarily. * - * The values -1 and 2 are special to isarr. It looks like 2 is - * some kind of an internal flag to do with whether the array's been - * copied, in which case I don't know why we don't use the copied - * flag, but they do both occur close together so they presumably - * have different effects. The value -1 is used to force us to - * keep an empty array. It's tested in the YUK chunk (I mean the - * one explicitly marked as such). + * The values -1 and 2 are special to isarr. The value -1 is used + * to force us to keep an empty array. It's tested in the YUK chunk + * (I mean the one explicitly marked as such). The value 2 + * indicates an array has come from splitting a scalar. We use + * that to override the usual rule that in double quotes we don't + * remove empty elements (so "${(s.:):-foo::bar}" produces two + * words). This seems to me to be quite the wrong thing to do, + * but it looks like code may be relying on it. So we require (@) + * as well before we keep the empty fields (look for assignments + * like "isarr = nojoin ? 1 : 2"). */ int isarr = 0; /* @@ -2453,7 +2456,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) char *arr[2], **t, **a, **p; if (spsep || spbreak) { aval = sepsplit(val, spsep, 0, 1); - isarr = 2; + isarr = nojoin ? 1 : 2; l = arrlen(aval); if (l && !*(aval[l-1])) l--; @@ -2772,7 +2775,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) else if (!aval[1]) val = aval[0]; else - isarr = 2; + isarr = nojoin ? 1 : 2; } if (isarr) l->list.flags |= LF_ARRAY; @@ -2974,7 +2977,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) val = getdata(firstnode(list)); else { aval = hlinklist2array(list, 0); - isarr = 2; + isarr = nojoin ? 1 : 2; l->list.flags |= LF_ARRAY; } copied = 1; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 1910e60be..e8718a691 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -942,3 +942,35 @@ >some >sunny >day + + foo="line:with::missing::fields:in:it" + print -l ${(s.:.)foo} +0:Removal of empty fields in unquoted splitting +>line +>with +>missing +>fields +>in +>it + + foo="line:with::missing::fields:in:it" + print -l "${(s.:.)foo}" +0:Hacky removal of empty fields in quoted splitting with no "@" +>line +>with +>missing +>fields +>in +>it + + foo="line:with::missing::fields:in:it" + print -l "${(@s.:.)foo}" +0:Retention of empty fields in quoted splitting with "@" +>line +>with +> +>missing +> +>fields +>in +>it -- cgit 1.4.1