table of Contents
Introduction
After Shell receives the command entered by the user, it will split the user's input into tokens according to the space. Then, the Shell will expand the special characters in the lemma, and the corresponding command will be called after the expansion is completed.
This kind of special character expansion is called pattern expansion (globbing). Some of them use wildcards, also known as wildcard expansion. Bash provides a total of eight extensions.
- Wavy line expansion
- ?Character expansion
- *Character expansion
- Bracket expansion
- Brace expansion
- Variable expansion
- Subcommand expansion
- Arithmetic expansion
This chapter introduces these eight extensions.
Bash expands first, and then executes commands. Therefore, Bash is responsible for the results of the expansion, and has nothing to do with the commands to be executed. There is no parameter expansion in the command itself, and the received parameters are executed as they are. This must be remembered.
The relationship between pattern expansion and regular expressions is that pattern expansion appears earlier than regular expressions and can be regarded as primitive regular expressions. Its functions are not as powerful and flexible as regular rules, but its advantages are simplicity and convenience.
Bash allows users to turn off extensions.
$ The SET -o noglob
# or
$ the SET -f
Copy the code
The following command can reopen the extension.
$ SET + O noglob
# or
$ SET + F
duplicated code
Wavy line expansion
Wavy line
$ echo ~
/home/me
Copy code
# Into the/home/me/foo directory
$ cd ~/foo
copy the code
$ echo ~foo
/home/foo
$ echo ~root
/root
Copy code
In the above example, Bash will return the user's home directory based on the user name after the tilde.
in case
$ echo ~nonExistedUser
~nonExistedUser
Copy code
$ cd ~/foo
$ echo ~+
/home/me/foo
Copy code
? Character expansion
# There are files a.txt and b.txt
$ ls ?.txt
a.txt b.txt
Copy code
In the above command,
If you match multiple characters, you need multiple
# There are files a.txt, b.txt and ab.txt
$ ls ??.txt
ab.txt
Copy code
ab.txt copy code
In the above command,
# There is a.txt file in the current directory
$ echo ?.txt
a.txt
# The current directory is an empty directory
$ echo ?.txt
?.TXT
Copy code
In the above example, if
* Character expansion
# There are files a.txt, b.txt and ab.txt
$ ls *.txt
a.txt b.txt ab.txt
Copy code
In the above example,
If you want to output all files in the current directory, use
$ ls * Copy code
# There are files a.txt, b.txt and ab.txt
$ ls a*.txt
a.txt ab.txt
$ ls *b*
b.txt ab.txt
Copy code
note,
If you want to match hidden files, you need to write
# Show all hidden files
$ echo .*
Copy code
If you want to match hidden files, you must also exclude
$ echo .[!.]*
Copy code
note,
# There is no file starting with c in the current directory
$ echo c*.txt
c*.txt
Copy code
In the above example, there is no
# Subdirectory has a.txt
# Invalid wording
$ ls *.txt
# Effective writing
$ ls */*.txt
Copy code
In the above example, the text file is in the subdirectory,
Bash 4.0 introduced a parameter
Bracket expansion
The form of square bracket expansion is
# There are files a.txt and b.txt
$ ls [ab].txt
a.txt b.txt
# Only the file a.txt exists
$ ls [ab].txt
a.txt
Copy code
In the above example,
Square bracket expansion belongs to file name matching, that is, the expanded result must conform to the existing file path. If there is no match, it will remain as it is, without expansion.
# The files a.txt and b.txt do not exist
$ ls [ab].txt
ls: can not access '[ab] .txt' : No such file or directory
copy the code
In the above example, since the expanded file does not exist,
There are two variants of square bracket expansion:
# There are three files aaa, bbb, aba
$ ls ?[!a]?
aba bbb
Copy code
In the above command,
Note that if you need to match
[start-end] extension
Bracket expansion has a shorthand form
# There are files a.txt, b.txt and c.txt
$ ls [ac].txt
a.txt
b.txt
c.txt
# There are files report1.txt, report2.txt and report3.txt
$ ls report[0-9].txt
report1.txt
report2.txt
report3.txt
...
Copy code
Here are some examples of common abbreviations.
- [az]: All lowercase letters.
- [a-zA-Z]: All lowercase and uppercase letters.
- [a-zA-Z0-9]: All lowercase letters, uppercase letters and numbers.
- [abc]*: All witha,b,cThe file name begins with one of the characters.
- program.[co]:fileprogram.cWith fileprogram.o.
- BACKUP.[0-9][0-9][0-9]: All withBACKUP.At the beginning, followed by the three-digit file name.
This short form has a negative form
$ echo report[!1 3].txt
report4.txt report5.txt
Copy code
In the above code,
Brace expansion
Brace expansion
$ echo {1,2,3}
1 2 3
$ echo d{a,e,i,u,o}g
dag deg dig dug dog
$ echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back
Copy code
Note that brace expansion is not a file name expansion. It will expand to all the given values, regardless of whether there is a corresponding file.
$ ls {a,b,c}.txt
ls: Cannot access'a.txt' : No such file or directory
ls: Cannot access'b.txt' : No such file or directory
ls: can not access 'c.txt' : No such file or directory
copy the code
In the above example, even if there is no corresponding file,
Another thing to note is that there can be no spaces before or after the comma inside the braces. Otherwise, brace expansion will fail.
$ echo {1, 2}
{1, 2}
Copy code
In the above example, there are spaces before and after the comma, Bash will think that this is not a brace expansion, but three independent parameters.
There can be no value before the comma, which means that the first item of the expansion is empty.
$ cp a.log{,.bak}
Equivalent to #
# cp a.log a.log.bak
duplicated code
Braces can be nested.
$ echo {j{p,pe}g,png}
jpg jpeg png
$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
Copy code
Braces can also be used in conjunction with other modes and are always expanded before other modes.
$ echo {cat,d*}
cat dawg dg dig dog doug dug
Copy code
In the above example, brace expansion will be performed first, and then
Braces can be used in multi-character patterns, square brackets are not acceptable (only single characters can be matched).
$ echo {cat,dog}
cat dog
Copy code
Due to brace expansion
# A.txt and b.txt do not exist
$ echo [ab].txt
[ab].txt
$ echo {a,b}.txt
a.txt b.txt
Copy code
In the above example, if it does not exist
{start..end} extension
There is a shorthand for brace expansion
$ echo {a..c}
abc
$ echo d{a..d}g
dag dbg dcg ddg
$ echo {1..4}
1 2 3 4
$ echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
Copy code
This abbreviation supports reverse order.
$ echo {c..a}
cba
$ echo {5..1}
5 4 3 2 1
Copy code
Note that if you encounter an incomprehensible abbreviation, the brace pattern will be output as it is, without expansion.
$ echo {a1..3c}
{a1..3c}
Copy code
This abbreviation can be nested to form a complex extension.
$ echo .{mp{3..4},m4{a,b,p,v}}
.mp3 .mp4 .m4a .m4b .m4p .m4v
Copy code
A common use for brace expansion is to create a series of directories.
$ mkdir {2007..2009}-{01..12} Copy code
The above command will create 36 new subdirectories, and the name of each subdirectory is "year-month".
Another common use of this wording is to use it directly
for I in {1..4}
do
echo $ I
DONE
duplicated code
The above example will loop 4 times.
If there is a leading in front of the integer
$ echo {01..5}
01 02 03 04 05
$ echo {001..5}
001 002 003 004 005
Copy code
This abbreviation can also use the second double dot (
$ echo {0..8..2}
0 2 4 6 8
Copy code
The above code will
Using multiple abbreviations together will have the effect of circular processing.
$ echo {a..c}{1..3}
a1 a2 a3 b1 b2 b3 c1 c2 c3
Copy code
Variable expansion
Bash puts the dollar sign
$ echo $SHELL
/bin/bash
Copy code
In addition to placing the variable name after the dollar sign, it can also be placed
$ echo ${SHELL}
/bin/bash
Copy code
$ echo ${!S*}
SECONDS SHELL SHELLOPTS SHLVL SSH_AGENT_PID SSH_AUTH_SOCK
Copy code
In the above example,
Subcommand expansion
$ echo $(date) Tue Jan 28 00:01:13 CST 2020 Copy code
In the above example,
There is another older syntax in which subcommands are placed in backticks, which can also be expanded into the result of the command.
$ echo `date`
Tue Jan 28 00:01:13 CST 2020
Copy code
Arithmetic expansion
$ echo $(( 2 + 2 ))
4
Copy code
Character class
- [[:alnum:]]: Match any English letter and number
- [[:alpha:]]: Match any English letter
- [[:blank:]]: Space and Tab key.
- [[:cntrl:]]: Unprintable characters of ASCII code 0-31.
- [[:digit:]]: Match any number 0-9.
- [[:graph:]]: AZ, az, 0-9 and punctuation marks.
- [[:lower:]]: Match any lowercase letter az.
- [[:print:]]: Printable characters with ASCII code 32-127.
- [[:punct:]]: Punctuation marks (except AZ, az, 0-9 printable characters).
- [[:space:]]: Space, Tab, LF (10), VT (11), FF (12), CR (13).
- [[:upper:]]: Match any uppercase letter AZ.
- [[:xdigit:]]: Hexadecimal characters (AF, af, 0-9).
Please see the example below.
$ echo [[:upper:]]*
Copy code
The above command outputs all file names beginning with capital letters.
An exclamation point can be added after the first square bracket of a character class
$ echo [![:digit:]]*
Copy code
The above command outputs all file names that do not start with a number.
The character class also belongs to the file name extension. If there is no matching file name, the character class will be output as it is.
# There is no file beginning with a capital letter
$ echo [[:upper:]]*
[[:upper:]]*
Copy code
In the above example, since there is no matching file, the character class is output as it is.
Points of Attention
There are some precautions for the use of wildcards.
(1) The wildcard is explained first, and then executed.
After receiving the command, Bash finds that there is a wildcard in it, it will expand the wildcard, and then execute the command.
$ ls a*.txt ab.txt Copy code
The execution process of the above command is that Bash first
(2) When the file name extension does not match, it will be output as it is.
The file name extension will be output as it is when there is no matching file.
# There is no file name beginning with r
$ echo r*
r*
Copy code
In the above code, because it does not exist
Here is another example.
$ ls *.csv ls: *.csv: No such file or directory Copy code
In addition, as mentioned earlier, brace expansion
(3) Only applicable to single-layer paths.
All file name extensions only match single-level paths and cannot match across directories, that is, files in subdirectories cannot be matched. Or,
If you want to match files in a subdirectory, you can write it as follows.
$ ls */*.txtCopy code
Bash 4.0 added a new one
(4) Wildcards can be used in the file name.
Bash allows wildcards in file names, that is, file names include special characters. To quote the file name at this time, you need to put the file name in single quotation marks.
$ touch'fo*'
$ ls
fo*
Copy code
The above code creates a
Quantifier
The quantifier is used to control the number of pattern matches. It's only in Bash
$ shopt extglob
extglob on
Copy code
There are several quantifiers as follows.
- ?(pattern-list): Match zero or one pattern.
- *(pattern-list): Match zero or more patterns.
- +(pattern-list): Match one or more patterns.
- @(pattern-list): Only match one pattern.
- !(pattern-list): Matches zero or more patterns, but does not match a single pattern.
$ ls abc?(.)txt abctxt abc.txt Copy code
In the above example,
$ ls abc?(def) abc abcdef Copy code
In the above example,
$ ls abc+(.txt|.php) abc.php abc.txt Copy code
In the above example,
$ ls abc+(.txt) abc.txt abc.txt.txt Copy code
In the above example,
The quantifier is also a file name extension. If there is no matching file, it will be output as it is.
# No file name starting with abc
$ ls abc?(def)
ls: can not access the 'abc (DEF)?' : No such file or directory
copy the code
In the above example, since there is no matching file,
shopt command
# Open a parameter
$ shopt -s [optionname]
# Turn off a parameter
$ shopt -u [optionname]
# Close or open a parameter query
$ shopt [Optionname]
Copy the code
(1) dotglob parameters
Under normal circumstances, the expansion result does not include hidden files.
$ ls * abc.txt Copy code
turn on
$ shopt -s dotglob
$ ls *
abc.txt .config
Copy code
(2) nullglob parameter
By default, wildcards will remain unchanged when they do not match any file name.
$ rm b*
rm: can not delete 'b *' : No such file or directory
copy the code
In the above example, because the current directory does not include
turn on
$ shopt -s nullglob
$ rm b*
rm: missing operand
Copy code
In the above example, since there is no
(3) Failglob parameter
$ shopt -s failglob
$ rm b*
bash: no match: b*
Copy code
In the above example, open
(4) extglob parameter
$ shopt extglob
extglob on
Copy code
Its main application is to support the quantification syntax. If you don't want to support the quantifier syntax, you can turn it off with the following command.
$ Shopt -u extglob
copy the code
(5) nocaseglob parameter
$ shopt -s nocaseglob
$ ls/windows/program*
/windows/ProgramData
/windows/Program Files
/windows/Program Files (x86)
Copy code
In the above example, open
(6) globstar parameters
Assume the following file structure.
a.txt sub1/b.txt sub1/sub2/c.txt Copy code
In the above file structure, the top-level directory and the first-level sub-directory
By default, it can only be written as follows.
$ ls *.txt */*.txt */*/*.txt a.txt sub1/b.txt sub1/sub2/c.txt Copy code
This is because
turn on
$ shopt -s globstar
$ ls **/*.txt
a.txt sub1/b.txt sub1/sub2/c.txt
Copy code
The next section introduces the quotes and escaping of the Bash script tutorial