Bash tutorial mode extension

Bash tutorial mode extension

table of Contents

 

Introduction

Wavy line expansion

? Character expansion

* Character expansion

Bracket expansion

[start-end] extension

Brace expansion

{start..end} extension

Variable expansion

Subcommand expansion

Arithmetic expansion

Character class

Points of Attention

Quantifier

shopt command


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.

globbing
This word comes from the early Unix system that had a
/etc/glob
File, save the expanded template. Later, Bash built this feature, but the name was retained.

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

~
Will automatically expand into the current user's home directory.

$ echo ~ /home/me Copy code

~/dir
Indicates that it is expanded into a subdirectory of the main directory,
dir
Is the name of a subdirectory in the main directory.

# Into the/home/me/foo directory $ cd ~/foo copy the code

~user
Means to expand into users
user
Home directory.

$ 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

~user
of
user
If the user name does not exist, the tilde expansion does not work.

$ echo ~nonExistedUser ~nonExistedUser Copy code

~+
Will expand to the current directory, which is equivalent to
pwd
command.

$ cd ~/foo $ echo ~+ /home/me/foo Copy code

 

?
Character expansion

?
The character represents any single character in the file path, excluding the null character. such as,
Data???
Match all
Data
A three-character file name follows.

# There are files a.txt and b.txt $ ls ?.txt a.txt b.txt Copy code

In the above command,

?
Represents a single character, so it will match at the same time
a.txt
with
b.txt
.

If you match multiple characters, you need multiple

?
Used together.

# There are files a.txt, b.txt and ab.txt $ ls ??.txt ab.txt Copy code
ab.txt copy code

In the above command,

??
Two characters were matched.

?
Character extension is a file name extension, and the extension will only occur if the file does exist. If the file does not exist, the expansion will not occur.

# 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

?.TXT
Can be expanded into a file name,
echo
The command will output the expanded result; if it cannot be expanded into a file name,
echo
Will output as it is
?.TXT
.

 

*
Character expansion

*
Characters represent any number of any characters in the file path, including zero characters.

# There are files a.txt, b.txt and ab.txt $ ls *.txt a.txt b.txt ab.txt Copy code

In the above example,

*.TXT
Represents the suffix
.TXT
All files.

If you want to output all files in the current directory, use

*
That's it.

$ ls * Copy code

*
Can match empty characters, the following is an example.

# 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,

*
Will not match hidden files (with
.
File at the beginning), that is
ls *
Hidden files will not be output.

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

.
with
..
These two special hidden files can be combined with square bracket expansion and written as
.[!.]*
.

$ echo .[!.]* Copy code

note,

*
Character extension is a file name extension, and it will only be extended if the file does exist. If the file does not exist, it will be output as it is.

# 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

c
At the beginning of the file, resulting in
c*.txt
It will be output as it is.

*
Only match the current directory, not subdirectories.

# 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,

*.TXT
Will not produce a match, it must be written as
*/*.TXT
. If there are several levels of subdirectories, you must write several levels of asterisks.

Bash 4.0 introduced a parameter

globstar
, When the parameter is turned on, allow
**
Match zero or more subdirectories. therefore,
**/*.TXT
It can match text files at the top level and text files in subdirectories of any depth. For details, please see the back
shopt
The introduction of the command.

 

Bracket expansion

The form of square bracket expansion is

[...]
, It will only be expanded if the file does exist. If the file does not exist, it will be output as it is. Any one of the characters in the brackets. such as,
[aeiou]
You can match any of the five vowels.

# 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,

[ab]
Can match
a
or
b
, Provided that the corresponding file does exist.

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,

[ab].txt
Output as it is, resulting in
ls
Naming error.

There are two variants of square bracket expansion:

[^...]
with
[!...]
. They mean to match characters that are not in square brackets, and these two wordings are equivalent. such as,
[^abc]
or
[!abc]
Means match except
a
,
b
,
c
Characters other than those.

# There are three files aaa, bbb, aba $ ls ?[!a]? aba bbb Copy code

In the above command,

[!a]
Indicates that the second character of the file name is not
a
File name, so it returns
aba
with
bbb
Two files.

Note that if you need to match

[
Characters can be placed in square brackets, such as
[[aeiou]
. If you need to match hyphens
-
, Can only be placed at the beginning or end of square brackets, such as
[-aeiou]
or
[aeiou-]
.

 

[start-end] extension

Bracket expansion has a shorthand form

[start-end]
, Which means to match a continuous range. such as,
[ac]
Equivalent to
[abc]
,
[0-9]
match
[0123456789]
.

# 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 with
    a
    ,
    b
    ,
    c
    The file name begins with one of the characters.
  • program.[co]
    :file
    program.c
    With file
    program.o
    .
  • BACKUP.[0-9][0-9][0-9]
    : All with
    BACKUP.
    At the beginning, followed by the three-digit file name.

This short form has a negative form

[!start-end]
, Which means to match characters that do not belong to this range. such as,
[!a-zA-Z]
Represents characters that match non-English letters.

$ echo report[!1 3].txt report4.txt report5.txt Copy code

 

In the above code,

[!1-3]
Indicates that 1, 2, and 3 are excluded.

 

Brace expansion

Brace expansion

{...}
Means to expand into all the values in the curly brackets, and separate the values with commas. such as,
{1,2,3}
Expand to
1 2 3
.

$ 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,

{a,b,c}
Still expanded into three file names, resulting in
ls
The command reported three errors.

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

*
Extension.

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

{...}
It is not a file name extension, so it will always be expanded. This is expanded with square brackets
[...]
It is completely different. If the matching file does not exist, the square brackets will not be expanded. At this point, we must pay attention to the distinction.

# 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

a.txt
with
b.txt
, Then
[ab].txt
Becomes a normal file name, and
{a,b}.txt
It can be extended in the same way.

 

{start..end} extension

There is a shorthand for brace expansion

{start..end}
, Which means to expand into a continuous sequence. such as,
{a..z}
Can be expanded into 26 lowercase English letters.

$ 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
cycle.

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

0
, Each item of the extended output has a leading
0
.

$ 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 (

start..end..step
), used to specify the step length of the expansion.

$ echo {0..8..2} 0 2 4 6 8 Copy code

The above code will

0
Expand to
8
, The length of each increment is
2
, So a total of 5 numbers are output.

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

$
The lemmas at the beginning are treated as variables and expanded into variable values

$ echo $SHELL /bin/bash Copy code

In addition to placing the variable name after the dollar sign, it can also be placed

${}
inside.

$ echo ${SHELL} /bin/bash Copy code

${!string*}
or
${!string@}
Return all matches the given string
string
The variable name.

$ echo ${!S*} SECONDS SHELL SHELLOPTS SHLVL SSH_AGENT_PID SSH_AUTH_SOCK Copy code

In the above example,

${!S*}
Expand to all
S
Variable name at the beginning.

 

Subcommand expansion

$(...)
It can be expanded to the result of another command, and all the output of this command will be used as the return value.

$ echo $(date) Tue Jan 28 00:01:13 CST 2020 Copy code

In the above example,

$(date)
return
date
The result of the command.

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

$(...)
Can be nested, such as
$(ls $(pwd))
.

 

Arithmetic expansion

$((...))
Can be expanded into the result of integer operations

$ echo $(( 2 + 2 )) 4 Copy code

 

Character class

[[:class:]]
Represents a character class, which expands to one of a certain class of specific characters. The commonly used character classes are as follows.

  • [[: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

!
, Which means negative. such as,
[![:digit:]]
Match all non-digits.

$ 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

a*.txt
Expand to
ab.txt
Before executing
ls ab.txt
.

(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

r
The file name at the beginning,
r*
It will be output as it is.

Here is another example.

$ ls *.csv ls: *.csv: No such file or directory Copy code

In addition, as mentioned earlier, brace expansion

{...}
Not a file name extension.

(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,

?
or
*
Such wildcards cannot match the path separator (
/
).

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

globstar
Parameters, allowed
**
Match zero or more subdirectories, see below for details
shopt
The introduction of the command.

(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

fo*
File at this time
*
Is part of the file name.

 

Quantifier

The quantifier is used to control the number of pattern matches. It's only in Bash

extglob
It can only be used when the parameter is turned on, but it is generally turned on by default. The following command can be inquired.

$ 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,

?(.)
Match zero or one point.

$ ls abc?(def) abc abcdef Copy code

In the above example,

?(def)
Match zero or one
def
.

$ ls abc+(.txt|.php) abc.php abc.txt Copy code

In the above example,

+(.txt|.php)
The matching file has one
.TXT
or
.php
Suffix name.

$ ls abc+(.txt) abc.txt abc.txt.txt Copy code

In the above example,

+(.txt)
There are one or more matching files
.TXT
Suffix name.

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,

abc?(def)
Output as is, resulting in
ls
The command reported an error.

 

shopt command

shopt
Commands can adjust Bash's behavior. It has several parameters related to wildcard expansion.

shopt
The usage of the command is as follows.

# 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

dotglob
The parameter allows the expansion result to include hidden files (that is, files beginning with a dot).

Under normal circumstances, the expansion result does not include hidden files.

$ ls * abc.txt Copy code

turn on

dotglob
, It will include hidden files.

$ shopt -s dotglob $ ls * abc.txt .config Copy code

(2) nullglob parameter

nullglob
The parameter allows you to return a null character when the wildcard character does not match any file name.

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

b
At the beginning of the file name, resulting in
b*
No file name expansion will occur and remain the same, so
rm
No command error
b*
This file.

turn on

nullglob
Parameter, you can let the unmatched wildcard return an empty string.

$ shopt -s nullglob $ rm b* rm: missing operand Copy code

In the above example, since there is no

b*
Matching file name, so
rm b*
Expanded into
rm
, Causing the error to become "missing operand".

(3) Failglob parameter

failglob
When the parameter causes the wildcard to match any file name, Bash will report an error directly instead of letting each command handle it.

$ shopt -s failglob $ rm b* bash: no match: b* Copy code

In the above example, open

failglob
In the future, due to
b*
Does not match any file name, Bash reports an error directly, no longer let
rm
Order to process.

(4) extglob parameter

extglob
The parameters enable Bash to support some extended syntax of ksh. It should be turned on by default.

$ 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

nocaseglob
Parameters can make wildcard expansion case-insensitive.

$ shopt -s nocaseglob $ ls/windows/program* /windows/ProgramData /windows/Program Files /windows/Program Files (x86) Copy code

In the above example, open

nocaseglob
after,
program*
It s not case sensitive and can match
ProgramData
Wait.

(6) globstar parameters

globstar
Parameters can make
**
Match zero or more subdirectories. This parameter is turned off by default.

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

sub1
, Second-level subdirectory
sub1\sub2
There is a text file in each. How can I use wildcards to display them?

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

*
Only match the current directory. If you want to match the subdirectories, you can only write it out layer by layer.

turn on

globstar
After the parameters,
**
Match zero or more subdirectories. therefore,
**/*.TXT
You can get the desired result.

$ 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