From: Peter Stephenson <pws@csr.com>
To: zsh-users@sunsite.dk
Subject: Re: Global History Substitution
Date: Fri, 4 Nov 2005 11:09:32 +0000 [thread overview]
Message-ID: <20051104110932.612805c7.pws@csr.com> (raw)
In-Reply-To: <20051103190747.GA16897@namib.cs.utk.edu>
Chris Johnson <cjohnson@cs.utk.edu> wrote:
> Is there a way to do global substitution on the previous command in ^
> notation? For instance,
>
> $ echo a b b b
> $ ^b^beta^
>
> yields
>
> $ echo a beta b b
>
> Certainly I could do !!:gs/b/beta. This isn't near as simple as
> something like gs/b/beta or ^b^beta^g. Anything I'm missing in the
> manual?
No, I think with this particular feature you're stuck. It's a historical
oddity that the "g" for global doesn't work as a qualifier, so the ^
notation is restricted.
It turns out that fixing the code to use :g like a qualifier isn't that
difficult, however... that's ^b^beta^:g, since if the colon is missing the
g is treated like ordinary text.
Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.57
diff -u -r1.57 expn.yo
--- Doc/Zsh/expn.yo 1 Nov 2005 18:04:25 -0000 1.57
+++ Doc/Zsh/expn.yo 4 Nov 2005 11:05:01 -0000
@@ -117,6 +117,8 @@
More precisely, the sequence `tt(^)var(foo)tt(^)var(bar)tt(^)' is
synonymous with `tt(!!:s)tt(^)var(foo)tt(^)var(bar)tt(^)', hence other
modifiers (see noderef(Modifiers)) may follow the final `tt(^)'.
+In particular, `tt(^)var(foo)tt(^)var(bar)tt(:g)' performs a global
+substitution.
If the shell encounters the character sequence `tt(!")'
in the input, the history mechanism is temporarily disabled until
@@ -254,10 +256,14 @@
)
item(tt(s/)var(l)tt(/)var(r)[tt(/)])(
Substitute var(r) for var(l) as described below.
-Unless preceded immediately by a tt(g), with no colon between,
-the substitution is done only for the
+The substitution is done only for the
first string that matches var(l). For arrays and for filename
generation, this applies to each word of the expanded text.
+
+The forms `tt(gs/)var(l)tt(/)var(r)' and `tt(s/)var(l)tt(/)var(r)tt(/:g)'
+perform global substitution, i.e. substitute every occurrence of var(r)
+for var(l). Note that the tt(g) or tt(:g) must appear in exactly the
+position shown.
)
item(tt(&))(
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
Index: Src/hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hist.c,v
retrieving revision 1.60
diff -u -r1.60 hist.c
--- Src/hist.c 10 Aug 2005 10:56:41 -0000 1.60
+++ Src/hist.c 4 Nov 2005 11:05:02 -0000
@@ -295,13 +295,27 @@
hwaddc(ingetc());
}
-/* extract :s/foo/bar/ delimiters and arguments */
+/*
+ * Extract :s/foo/bar/ delimiters and arguments
+ *
+ * The first character expected is the first delimiter.
+ * The arguments are stored in the hsubl and hsubr variables.
+ *
+ * subline is the part of the command line to be matched.
+ *
+ * *gbalp is set to 1 to indicate a trailing ':g', i.e. a
+ * global substitution.
+ *
+ * If a ':' was found but was not followed by a 'g',
+ * *cflagp is set to 1 and the input is backed up to the
+ * character following the colon.
+ */
/**/
static int
-getsubsargs(char *subline)
+getsubsargs(char *subline, int *gbalp, int *cflagp)
{
- int del;
+ int del, follow;
char *ptr1, *ptr2;
del = ingetc();
@@ -315,6 +329,17 @@
}
zsfree(hsubr);
hsubr = ptr2;
+ follow = ingetc();
+ if (follow == ':') {
+ follow = ingetc();
+ if (follow == 'g')
+ *gbalp = 1;
+ else {
+ inungetc(follow);
+ *cflagp = 1;
+ }
+ } else
+ inungetc(follow);
if (hsubl && !strstr(subline, hsubl)) {
herrflush();
zerr("substitution failed", NULL, 0);
@@ -348,14 +373,16 @@
/* look, no goto's */
if (isfirstch && c == hatchar) {
+ int gbal = 0;
+
/* Line begins ^foo^bar */
isfirstch = 0;
inungetc(hatchar);
if (!(ehist = gethist(defev))
|| !(sline = getargs(ehist, 0, getargc(ehist)))
- || getsubsargs(sline) || !hsubl)
+ || getsubsargs(sline, &gbal, &cflag) || !hsubl)
return -1;
- subst(&sline, hsubl, hsubr, 0);
+ subst(&sline, hsubl, hsubr, gbal);
} else {
/* Line doesn't begin ^foo^bar */
if (c != ' ')
@@ -577,7 +604,7 @@
}
break;
case 's':
- if (getsubsargs(sline))
+ if (getsubsargs(sline, &gbal, &cflag))
return -1; /* fall through */
case '&':
if (hsubl && hsubr)
--
Peter Stephenson <pws@csr.com> Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070
This message has been scanned for viruses by BlackSpider MailControl - www.blackspider.com
next prev parent reply other threads:[~2005-11-04 11:09 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-03 19:07 Chris Johnson
2005-11-03 19:36 ` Philip Kizer
2005-11-03 22:08 ` zzapper
2005-11-04 11:09 ` Peter Stephenson [this message]
2005-11-04 11:30 ` Peter Stephenson
2005-11-04 13:12 ` zzapper
2005-11-04 15:13 ` Bart Schaefer
2005-11-04 16:12 ` Peter Stephenson
2005-11-08 19:07 ` zzapper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20051104110932.612805c7.pws@csr.com \
--to=pws@csr.com \
--cc=zsh-users@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).