From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh Users <zsh-users@zsh.org>
Subject: Re: difference between ~ & ^ negation
Date: Fri, 3 Jan 2014 20:10:56 +0000 [thread overview]
Message-ID: <20140103201056.1bb2dc32@pws-pc.ntlworld.com> (raw)
In-Reply-To: <20140103194802.2f7cae9d@pws-pc.ntlworld.com>
On Fri, 3 Jan 2014 19:48:02 +0000
Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> Here's an FAQ entry on ^ and ~ since they are obvious confusing.
Corrections I spotted myself before anyone else picks nits.
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index bd8ca97..bb17ceb 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -122,6 +122,7 @@ Chapter 3: How to get various things to work
3.24. What's wrong with cut and paste on my xterm?
3.25. How do I get coloured prompts on my colour xterm?
3.26. Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?
+3.27. What are these `^' and `~' pattern characters, anyway?
Chapter 4: The mysteries of completion
4.1. What is completion?
@@ -545,14 +546,8 @@ tt(EXTENDED_GLOB).
option tt(KSH_GLOB) is in effect; for previous versions you
must use the table above.
- [1] Note that mytt(~) is the only globbing operator to have a lower
- precedence than mytt(/). For example, mytt(**/foo~*bar*) matches any
- file in a subdirectory called mytt(foo), except where mytt(bar)
- occurred somewhere in the path (e.g. mytt(users/barstaff/foo) will
- be excluded by the mytt(~) operator). As the mytt(**) operator cannot
- be grouped (inside parentheses it is treated as mytt(*)), this is
- one way to exclude some subdirectories from matching a mytt(**).
- The form (^foo/)# also works.
+ [1] See question link(3.27)(327) for more on the mysteries of
+ mytt(~) and mytt(^).
it() Unquoted assignments do file expansion after mytt(:)s (intended for
PATHs).
it()* mytt(typeset) and mytt(integer) have special behaviour for
@@ -1452,6 +1447,8 @@ sect(Why does mytt(bindkey ^a command-name) or mytt(stty intr ^-) do something f
are metacharacters. tt(^a) matches any file except one called tt(a), so the
line is interpreted as bindkey followed by a list of files. Quote the
tt(^) with a backslash or put quotation marks around tt(^a).
+ See link(3.27)(327) if you want to know more about the pattern
+ character mytt(^).
sect(Why can't I bind tt(\C-s) and tt(\C-q) any more?)
@@ -1668,6 +1665,7 @@ sect(How do I prevent the prompt overwriting output when there is no newline?)
One final alternative is to put a newline in your prompt -- see question
link(3.13)(313) for that.
+
sect(What's wrong with cut and paste on my xterm?)
On the majority of modern UNIX systems, cutting text from one window and
@@ -1700,6 +1698,7 @@ sect(What's wrong with cut and paste on my xterm?)
fixes referred to above in order to be reliable).
)
+
sect(How do I get coloured prompts on my colour xterm?)
(Or `color xterm', if you're reading this in black and white.)
@@ -1743,6 +1742,7 @@ sect(How do I get coloured prompts on my colour xterm?)
`mytt(<ESC>[0m)' puts printing back to normal so that the rest of the line
is unchanged.
+
sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
This is a slightly unexpected effect of the option tt(MULTIOS), which is
@@ -1780,6 +1780,128 @@ sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
to unset the option mytt(MULTIOS).
+sect(What are these `^' and `~' pattern characters, anyway?)
+label(327)
+
+ The characters mytt(^) and mytt(~) are active when the option
+ tt(EXTENDED_GLOB) is set. Both are used to exclude patterns, i.e. to
+ say `match something other than ...'. There are some confusing
+ differences, however. Here are the descriptions for mytt(^) and mytt(~).
+
+ mytt(^) means `anything except the pattern that follows'. You can
+ think of the combination tt(^)em(pat) as being like a tt(*) except
+ that it doesn't match em(pat). So, for example, mytt(myfile^.txt)
+ matches anything that begins with tt(myfile) except tt(myfile.txt).
+ Because it works with patterns, not just strings, mytt(myfile^*.c)
+ matches anything that begins with tt(myfile) unless it ends with
+ tt(.c), whatever comes in the middle --- so it matches tt(myfile1.h)
+ but not tt(myfile1.c).
+
+ Also like mytt(*), mytt(^) doesn't match across directories if you're
+ matching files when `globbing', i.e. when you use an unquoted pattern
+ in an ordinary command line to generate file names. So
+ mytt(^dir1/^file1) matches any subdirectory of the current directory
+ except one called tt(dir1), and within any directory it matches it
+ picks any file except one called tt(file1). So the overall pattern
+ matches tt(dir2/file2) but not tt(dir1/file1) nor tt(dir1/file2) nor
+ tt(dir2/file1). (The rule that all the different bits of the pattern
+ must match is exactly the same as for any other pattern character,
+ it's just a little confusing that what em(does) match in each bit is
+ found by telling the shell em(not) to match something or other.)
+
+ As with any other pattern, a mytt(^) expression doesn't treat the
+ character `tt(/)' specially if it's not matching files, for example
+ when pattern matching in a command like mytt([[ $string = ^pat1/pat2 ]]).
+ Here the whole string tt(pat1/pat2) is treated as the argument that
+ follows the mytt(^). So anything matches but that one string
+ tt(pat1/pat1).
+
+ It's not obvious what something like mytt([[ $string = ^pat1^pat2 ]])
+ means. You won't often have cause to use it, but the rule is that
+ each mytt(^) takes em(everything) that follows as an argument (unless
+ it's already inside parentheses --- I'll explain this below). To see
+ this more clearly, put those arguments in parentheses: the pattern is
+ equivalent to mytt(^(pat1^(pat2))). where now you can see exactly what
+ each mytt(^) takes as its argument. I'll leave it as an exercise for
+ you to work out what this does and doesn't match.
+
+ mytt(~) is always used between two patterns --- never right at the
+ beginning or right at the end. Note that the other special meaning of
+ mytt(~), at the start of a filename to refer to your home directory or
+ the another named directory, doesn't require the option
+ tt(EXTENDED_GLOB) to be set. (At the end of an argument mytt(~) is
+ never special at all. This is useful if you have Emacs backup files.)
+ It means `match what's in front of the tilde, but only if it doesn't
+ match what's after the tilde'. So mytt(*.c~f*) matches any file
+ ending in tt(.c) except one that begins with tt(f). You'll see that,
+ unlike mytt(^), the parts before and after the mytt(~) both refer
+ separately to the entire test string.
+
+ For matching files by globbing, mytt(~) is the only globbing
+ operator to have a lower precedence than mytt(/). In other words,
+ when you have mytt(/a/path/to/match~/a/path/not/to/match) the mytt(~)
+ considers what's before and what's after as complete paths to file names.
+ You can put any other pattern characters in the expressions before and
+ after the mytt(~), but note that the pattern after the tt(~) is really
+ just a single pattern to match against every file found. That means,
+ for example, that a tt(*) after the tt(~) em(will) match a tt(/).
+ If that's confusing, you can think of how mytt(~) works like this:
+ take the pattern on the left, use it as normal to make a list of
+ files, then for each file found see if it matches the pattern on the
+ right and if it does take that file out of the list.
+
+ One rule that is common to both mytt(^) and mytt(~) is that they can
+ be put inside parentheses and the arguments to them don't extend past
+ the parentheses. So mytt((^README).txt) matches any file ending in
+ tt(.txt) unless the string before that was tt(README), the same as
+ mytt(*.txt~README.txt) or mytt((*~README).txt). In fact, you can
+ always turn mytt(^something) into mytt((*~something)), where
+ mytt(something) mustn't contain tt(/) if the pattern is being used for
+ globbing.
+
+ Likewise, mytt(abc(<->~<10-100>).txt) matches a file consisting of
+ tt(abc), then some digits, then tt(.txt), unless the digits happen to
+ match a number from 10 to 100 inclusive (remember the handy mytt(<->)
+ pattern for matching integers with optional limits to the range). So
+ this pattern matches tt(abc1.txt) or tt(abc200.txt) but not
+ tt(abc20.txt) nor tt(abc100.txt) nor even tt(abc0030.txt). However,
+ if you're matching files by globbing note you can't put mytt(/)s
+ inside the parentheses since the groups can't stretch across multiple
+ directories. (You can do that, of course, whenever the character
+ mytt(/) isn't special.)
+
+ You may like to know that from zsh 5.0.3 you can disable any pattern
+ character separately. So if you find mytt(^) gets in your way and
+ you're happy using mytt(~), put mytt(disable -p "^") in tt(~/.zshrc).
+ You still need to turn on tt(EXTENDED_GLOB); the tt(disable) command
+ only deactivates things that would otherwise be active, you can't
+ specially enable something not allowed by the syntax options in effect.
+
+ Here are some examples with files to illustrate the points. We'll
+ assume the option tt(EXTENDED_GLOB) is set and none of the pattern
+ characters is disabled.
+
+ enumerate(
+ myeit() mytt(**/foo~*bar*) matches any file called mytt(foo) in any
+ subdirectory, except where mytt(bar) occurred somewhere in the path.
+ For example, mytt(users/barstaff/foo) will be excluded by the mytt(~)
+ operator. As the mytt(**) operator cannot be grouped (inside
+ parentheses it is treated as mytt(*)), this is one way to exclude some
+ subdirectories from matching a mytt(**). Note that this can be quite
+ inefficent because the shell performs a complete search for
+ mytt(**/foo) before it uses the pattern after the mytt(~) to exclude
+ files from the match. The file is excluded if mytt(bar) occurs
+ em(anywhere), in any directory segment or the final file name.
+ myeit() The form mytt((^foo/)#) can be used to match any hierarchy of
+ directories where none of the path components is tt(foo). For
+ example, mytt((^CVS/)#) selects all subdirectories to any depth
+ except where one component is named mytt(CVS). (The form
+ mytt((pat/)#) is very useful in other cases; for example,
+ mytt((../)#.cvsignore) finds the file tt(.cvsignore) if it exists
+ in the current directory or any parent.)
+ )
+
+
chapter(The mysteries of completion)
--
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
next prev parent reply other threads:[~2014-01-03 20:17 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-01 15:28 zzapper
2014-01-01 21:44 ` Bart Schaefer
2014-01-02 21:01 ` Peter Stephenson
2014-01-02 21:36 ` Bart Schaefer
2014-01-02 22:14 ` Peter Stephenson
2014-01-03 1:55 ` Mikael Magnusson
2014-01-03 7:37 ` Bart Schaefer
2014-01-03 19:48 ` Peter Stephenson
2014-01-03 20:10 ` Peter Stephenson [this message]
2014-01-03 21:43 ` Bart Schaefer
2014-01-04 21:11 ` zzapper
2014-01-05 10:01 ` Eike von Seggern
[not found] ` <8lp61n01B02mHnv01lp8uc>
2014-01-03 20:56 ` how to shut off auto spell steve
2014-01-03 21:52 ` Bart Schaefer
[not found] ` <9ZwH1n01Z02mHnv01ZwLWZ>
2014-01-03 22:07 ` steve
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=20140103201056.1bb2dc32@pws-pc.ntlworld.com \
--to=p.w.stephenson@ntlworld.com \
--cc=zsh-users@zsh.org \
/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).