shell编程

linux

本文主要介绍shell编程的基本语法以及实际应用中的常见命令。

1. 注释

1.1. 单行注释

# 这是单行注释

1.2. 多行注释

:<<EOF
多行注释内容
多行注释内容
多行注释内容
EOF

多行注释EOF也可替换成!'

:<<'
多行注释内容
多行注释内容
多行注释内容
'

:<<!
多行注释内容
多行注释内容
多行注释内容
!

2. 变量

2.1. 变量定义

使用VARIABLENAME=VALUE的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。

2.2. 变量使用

只需要在变量前加$符号,变量加{}是可选的,方便解释器识别边界。将变量加上{}是一个好习惯,不容易出错。

your_age=25
your_name="shinerio"
your_name=shinerio
your_name='shinerio'
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo "${your_name}hello" <span class="tag">#这里</span>{}必须添加,否则解释器认为是${your_namehello}
str='hello'' # 非法
str='hello'__'world' # 成对出现的单引号做字符拼接
echo $str <span class="tag">#输出hello__world</span>
str1='helloworld${your_age}\nnew line'
str2="helloworld${your_age}\nnew line"
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
<span class="tag">#helloworld25</span>
<span class="tag">#new</span> line

2.3. 只读变量

使用readonly VARIABLENAME设置变量只读,只读变量的值不能更改

readonly name='jack'
name='kelly'
zsh: read-only variable: name

2.4. 删除变量

使用unset VARIABLENAME删除变量。

3. 字符串操作

3.1. 字符串拼接

str1="hello"${your_name}"world"
str2="hello${your_name}world"
str3='hello'${your_name}'world'

3.2. 字符串长度

str='hello'
echo ${<span class="tag">#str</span>}
5

3.3. 字符串截取

${string:start:length},索引从0开始,从start(包含)开始截取共计length长度的字符。

str='helloworld'
echo ${str:0:5}
hello

3.4. 字符串运算符

运算符 说明 举例
= 检测两个字符串是否相等,相等返回true [ 'hello' = 'hello' ]
!= 检测两个字符串是否相等,不相等返回true [ 'hello' != 'ello' ]
-z 检测字符串长度是否为0,为0返回true [ -z '' ]
-n 检测字符串长度是否不为0,不为0返回true [ -n 'hello' ]
$ 检测字符串是否为空,不为空返回true [ <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p> <h1>1. 注释</h1> <h2>1.1. 单行注释</h2> <pre><code class="language-shell"># 这是单行注释 </code></pre> <h2>1.2. 多行注释</h2> <pre><code class="language-shell">:&lt;&lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF </code></pre> <p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p> <pre><code class="language-shell">:&lt;&lt;&#39; 多行注释内容 多行注释内容 多行注释内容 &#39; :&lt;&lt;! 多行注释内容 多行注释内容 多行注释内容 ! </code></pre> <h1>2. 变量</h1> <h2>2.1. 变量定义</h2> <p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p> <h2>2.2. 变量使用</h2> <p>只需要在变量前加<code><article> <header> <h1>shell编程</h1> <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time> <div class="tags"> <span class="tag">linux</span> </div> </header> <section class="content"> <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p> <h1>1. 注释</h1> <h2>1.1. 单行注释</h2> <pre><code class="language-shell"># 这是单行注释 </code></pre> <h2>1.2. 多行注释</h2> <pre><code class="language-shell">:&lt;&lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF </code></pre> <p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p> <pre><code class="language-shell">:&lt;&lt;&#39; 多行注释内容 多行注释内容 多行注释内容 &#39; :&lt;&lt;! 多行注释内容 多行注释内容 多行注释内容 ! </code></pre> <h1>2. 变量</h1> <h2>2.1. 变量定义</h2> <p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p> <h2>2.2. 变量使用</h2> <p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p> <pre><code class="language-shell">your_age=25 your_name=&quot;shinerio&quot; your_name=shinerio your_name=&#39;shinerio&#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello} str=&#39;hello&#39;&#39; # 非法 str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接 echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt; str1=&#39;helloworld${your_age}\nnew line&#39; str2=&quot;helloworld${your_age}\nnew line&quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt; &lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line </code></pre> <h2>2.3. 只读变量</h2> <p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p> <pre><code class="language-shell">readonly name=&#39;jack&#39; name=&#39;kelly&#39; zsh: read-only variable: name </code></pre> <h2>2.4. 删除变量</h2> <p>使用<code>unset VARIABLENAME</code>删除变量。</p> <h1>3. 字符串操作</h1> <h2>3.1. 字符串拼接</h2> <pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot; str2=&quot;hello${your_name}world&quot; str3=&#39;hello&#39;${your_name}&#39;world&#39; </code></pre> <h2>3.2. 字符串长度</h2> <pre><code class="language-shell">str=&#39;hello&#39; echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;} 5 </code></pre> <h2>3.3. 字符串截取</h2> <p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p> <pre><code class="language-shell">str=&#39;helloworld&#39; echo ${str:0:5} hello </code></pre> <h2>3.4. 字符串运算符</h2> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>=</code></td> <td>检测两个字符串是否相等,相等返回true</td> <td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>!=</code></td> <td>检测两个字符串是否相等,不相等返回true</td> <td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td> </tr> <tr> <td><code>-z</code></td> <td>检测字符串长度是否为0,为0返回true</td> <td><code>[ -z &#39;&#39; ]</code></td> </tr> <tr> <td><code>-n </code></td> <td>检测字符串长度是否不为0,不为0返回true</td> <td><code>[ -n &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>$</code></td> <td>检测字符串是否为空,不为空返回true</td> <td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi # hello if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi # hello if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ];then echo &#39;hello&#39;;fi str=&#39;hello&#39; if [ $str ];then echo &#39;hello&#39;;fi # hello </code></pre> <p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p> <h1>4. 文件测试运算符</h1> <table> <thead> <tr> <th>操作符</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>-b file</code></td> <td>检测文件是否是块设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-c file</code></td> <td>检测文件是否是字符设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-d file</code></td> <td>检测文件是否是目录,如果是,则返回true。</td> </tr> <tr> <td><code>-f file</code></td> <td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td> </tr> <tr> <td><code>-g file</code></td> <td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-k file</code></td> <td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td> </tr> <tr> <td><code>-p file</code></td> <td>检测文件是否是有名管道,如果是,则返回true。</td> </tr> <tr> <td><code>-u file</code></td> <td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-r file</code></td> <td>检测文件是否可读,如果是,则返回true。</td> </tr> <tr> <td><code>-w file</code></td> <td>检测文件是否可写,如果是,则返回true。</td> </tr> <tr> <td><code>-x file</code></td> <td>检测文件是否可执行,如果是,则返回true。</td> </tr> <tr> <td><code>-s file</code></td> <td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td> </tr> <tr> <td><code>-e file</code></td> <td>检测文件(包括目录)是否存在,如果是,则返回true。</td> </tr> </tbody></table> <pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # file if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # directory if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi # not exist </code></pre> <h1>5. 数组</h1> <p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p> <ul> <li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li> <li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li> <li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li> </ul> <pre><code class="language-shell">arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&#39;new_value3&#39; echo $arr[3] # new_value3 echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]} # 4 echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; # arr[1]的长度为:6 </code></pre> <h1>6. 运算符</h1> <h2>6.1. 赋值运算符</h2> <pre><code class="language-shell">a=10 b=$a </code></pre> <h2>6.2. 算术运算符</h2> <p>算数运算符支持<code>+,-,*,/,%</code></p> <h3>6.2.1. expr表示法</h3> <pre><code class="language-shell">echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 </code></pre> <blockquote> <p>使用expr表示方法时,表达式和运算符之间必须有空格。</p> </blockquote> <h3>6.2.2. <code>$[]</code></h3> <pre><code class="language-shell">echo $[10%3] # 1 </code></pre> <h3>6.2.3. <code>$(())</code></h3> <pre><code class="language-shell">echo $((10*20)) # 200 </code></pre> <h2>6.3. 关系运算符</h2> <p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p> <pre><code class="language-shell">echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&gt;=10] # 1 </code></pre> <p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p> <blockquote> <p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p> </blockquote> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>-eq</code></td> <td>检测两个数是否相等,相等返回true。</td> <td><code>[ $a -eq $b ]</code></td> </tr> <tr> <td><code>-ne</code></td> <td>检测两个数是否不相等,不相等返回 true。</td> <td><code>[ $a -ne $b ]</code></td> </tr> <tr> <td><code>-gt</code></td> <td>检测左边的数是否大于右边的,如果是,则返回 true。</td> <td><code>[ $a -gt $b ]</code></td> </tr> <tr> <td><code>-lt</code></td> <td>检测左边的数是否小于右边的,如果是,则返回 true。</td> <td><code>[ $a -lt $b ]</code></td> </tr> <tr> <td><code>-ge</code></td> <td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -ge $b ]</code></td> </tr> <tr> <td><code>-le</code></td> <td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -le $b ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi; # hello if ((10&gt;=10));then echo &#39;hello&#39;;fi; # hello </code></pre> <h2>6.4. 布尔、逻辑运算符</h2> <p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>!</code></td> <td>非运算,表达式为true则返回false,否则返回true。</td> <td><code>[ ! 10 -eq 0 ]</code></td> </tr> <tr> <td><code>-o</code></td> <td>或运算,有一个表达式为true则返回true。</td> <td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td> </tr> <tr> <td><code>-a</code></td> <td>与运算,两个表达式都为true才返回true。</td> <td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi # hello </code></pre> <p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p> <pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi # hello if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi # hello </code></pre> <h1>7. 传递参数</h1> <p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p> <table> <thead> <tr> <th>参数处理</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>$#</code></td> <td>传递到脚本的参数个数</td> </tr> <tr> <td><code>$*</code></td> <td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$</code></td> <td>脚本运行的当前进程ID号</td> </tr> <tr> <td><code>$!</code></td> <td>后台运行的最后一个进程的ID号</td> </tr> <tr> <td><code>$@</code></td> <td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$-</code></td> <td>显示Shell使用的当前选项,与set功能相同。</td> </tr> <tr> <td><code>$?</code></td> <td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td> </tr> </tbody></table> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-bash">set -e echo &quot;执行的文件名:$0&quot; echo &quot;参数个数为$#&quot; echo &quot;第一个参数为:$1&quot; echo &quot;第二个参数为:$2&quot; echo &quot;所有参数为:$@&quot; echo &quot;进程ID号为:$&quot; echo &quot;当前shell选项为$-&quot; echo &quot;上一个命令退出的状态为$?&quot; </code></pre> <p>执行结果如下:</p> <pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 </code></pre> <h1>8. 函数</h1> <p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-shell">sayhello(){ echo &quot;hello&quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &quot;hello, $1 $2 $3&quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? </code></pre> <p>输出如下:</p> <blockquote> <p>hello<br>hello, zhangsan lisi wangwu<br>1</p> </blockquote> <h1>9. 命令替换</h1> <p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p> <pre><code class="language-shell"># command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 </code></pre> <h1>10. let命令</h1> <p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p> <ul> <li>自加操作:<code>let no++</code></li> <li>自减操作:<code>let no--</code></li> <li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li> </ul> <h1>11. 流程控制</h1> <h2>11.1. if</h2> <pre><code class="language-shell">if ((10&lt;2));then echo &quot;10小于2&quot; elif ((10&gt;20));then echo &quot;a大于10&quot; else echo &quot;10大于2且小于10&quot; fi </code></pre> <h2>11.2. case</h2> <p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p> <pre><code class="language-shell">case 10 in 0|1) echo &quot;a为0或1&quot; ;; 11|12) echo &quot;a为11或12&quot; ;; *) # *用来匹配所有情况 echo &quot;a为10&quot; ;; esac </code></pre> <h2>11.3. while</h2> <pre><code class="language-shell">count=0 while(($count&lt;5)) do echo $count let count++ done </code></pre> <h2>11.4. util</h2> <pre><code class="language-shell">count=0 until(($count&gt;=5)) do echo $count let count++ done </code></pre> <h2>11.5. for</h2> <pre><code class="language-shell"># for写法1 for ((count=0;$count&lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done </code></pre> <h2>11.6. break和continue</h2> <p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p> <pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1)) do     if (($count&gt;=5));then         break;     fi     echo $count done </code></pre> <h1>12. 输入输出重定向</h1> <h2>12.1. 输出重定向</h2> <p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p> <pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看 who &gt; users # 将字符串hello world保存到text.txt文件中 echo &quot;hello world&quot; &gt; text.txt </code></pre> <h2>12.2. 输入重定向</h2> <p><code>command &lt; file</code>从file文件获取输入</p> <pre><code class="language-shell">wc -l /etc/passwd # 123 /etc/passwd wc -l &lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &lt; /etc/passwd &gt; result cat result # 123 </code></pre> <h2>12.3. 文件描述符</h2> <p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p> <ul> <li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li> <li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li> <li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li> </ul> <pre><code class="language-shell"># 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;&gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &gt; result 2&gt;&amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&gt;result 2&gt;error_trace </code></pre> <h2>12.4. Here Document</h2> <p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p> <pre><code class="language-bash"># command &lt;&lt; EOF # document # EOF cat &lt;&lt; EOF hello shinerio learn shell EOF </code></pre> <blockquote> <p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p> </blockquote> <h2>12.5. /dev/null</h2> <p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p> <pre><code class="language-shell">cat users &gt; /dev/null cat users &gt; /dev/null 2&gt;&amp;1 </code></pre> <h1>13. set命令</h1> <p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p> <ul> <li>-e  若指令传回值不等于0,则立即退出shell。</li> <li>-f  取消使用通配符。</li> <li>-n  只读取指令,而不实际执行。</li> <li>-x  执行指令后,会先显示该指令及所下的参数。</li> </ul> </section> </article>lt;/code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p> <pre><code class="language-shell">your_age=25 your_name=&quot;shinerio&quot; your_name=shinerio your_name=&#39;shinerio&#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello} str=&#39;hello&#39;&#39; # 非法 str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接 echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt; str1=&#39;helloworld${your_age}\nnew line&#39; str2=&quot;helloworld${your_age}\nnew line&quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt; &lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line </code></pre> <h2>2.3. 只读变量</h2> <p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p> <pre><code class="language-shell">readonly name=&#39;jack&#39; name=&#39;kelly&#39; zsh: read-only variable: name </code></pre> <h2>2.4. 删除变量</h2> <p>使用<code>unset VARIABLENAME</code>删除变量。</p> <h1>3. 字符串操作</h1> <h2>3.1. 字符串拼接</h2> <pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot; str2=&quot;hello${your_name}world&quot; str3=&#39;hello&#39;${your_name}&#39;world&#39; </code></pre> <h2>3.2. 字符串长度</h2> <pre><code class="language-shell">str=&#39;hello&#39; echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;} 5 </code></pre> <h2>3.3. 字符串截取</h2> <p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p> <pre><code class="language-shell">str=&#39;helloworld&#39; echo ${str:0:5} hello </code></pre> <h2>3.4. 字符串运算符</h2> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>=</code></td> <td>检测两个字符串是否相等,相等返回true</td> <td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>!=</code></td> <td>检测两个字符串是否相等,不相等返回true</td> <td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td> </tr> <tr> <td><code>-z</code></td> <td>检测字符串长度是否为0,为0返回true</td> <td><code>[ -z &#39;&#39; ]</code></td> </tr> <tr> <td><code>-n </code></td> <td>检测字符串长度是否不为0,不为0返回true</td> <td><code>[ -n &#39;hello&#39; ]</code></td> </tr> <tr> <td><code><article> <header> <h1>shell编程</h1> <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time> <div class="tags"> <span class="tag">linux</span> </div> </header> <section class="content"> <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p> <h1>1. 注释</h1> <h2>1.1. 单行注释</h2> <pre><code class="language-shell"># 这是单行注释 </code></pre> <h2>1.2. 多行注释</h2> <pre><code class="language-shell">:&lt;&lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF </code></pre> <p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p> <pre><code class="language-shell">:&lt;&lt;&#39; 多行注释内容 多行注释内容 多行注释内容 &#39; :&lt;&lt;! 多行注释内容 多行注释内容 多行注释内容 ! </code></pre> <h1>2. 变量</h1> <h2>2.1. 变量定义</h2> <p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p> <h2>2.2. 变量使用</h2> <p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p> <pre><code class="language-shell">your_age=25 your_name=&quot;shinerio&quot; your_name=shinerio your_name=&#39;shinerio&#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello} str=&#39;hello&#39;&#39; # 非法 str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接 echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt; str1=&#39;helloworld${your_age}\nnew line&#39; str2=&quot;helloworld${your_age}\nnew line&quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt; &lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line </code></pre> <h2>2.3. 只读变量</h2> <p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p> <pre><code class="language-shell">readonly name=&#39;jack&#39; name=&#39;kelly&#39; zsh: read-only variable: name </code></pre> <h2>2.4. 删除变量</h2> <p>使用<code>unset VARIABLENAME</code>删除变量。</p> <h1>3. 字符串操作</h1> <h2>3.1. 字符串拼接</h2> <pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot; str2=&quot;hello${your_name}world&quot; str3=&#39;hello&#39;${your_name}&#39;world&#39; </code></pre> <h2>3.2. 字符串长度</h2> <pre><code class="language-shell">str=&#39;hello&#39; echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;} 5 </code></pre> <h2>3.3. 字符串截取</h2> <p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p> <pre><code class="language-shell">str=&#39;helloworld&#39; echo ${str:0:5} hello </code></pre> <h2>3.4. 字符串运算符</h2> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>=</code></td> <td>检测两个字符串是否相等,相等返回true</td> <td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>!=</code></td> <td>检测两个字符串是否相等,不相等返回true</td> <td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td> </tr> <tr> <td><code>-z</code></td> <td>检测字符串长度是否为0,为0返回true</td> <td><code>[ -z &#39;&#39; ]</code></td> </tr> <tr> <td><code>-n </code></td> <td>检测字符串长度是否不为0,不为0返回true</td> <td><code>[ -n &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>$</code></td> <td>检测字符串是否为空,不为空返回true</td> <td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi # hello if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi # hello if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ];then echo &#39;hello&#39;;fi str=&#39;hello&#39; if [ $str ];then echo &#39;hello&#39;;fi # hello </code></pre> <p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p> <h1>4. 文件测试运算符</h1> <table> <thead> <tr> <th>操作符</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>-b file</code></td> <td>检测文件是否是块设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-c file</code></td> <td>检测文件是否是字符设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-d file</code></td> <td>检测文件是否是目录,如果是,则返回true。</td> </tr> <tr> <td><code>-f file</code></td> <td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td> </tr> <tr> <td><code>-g file</code></td> <td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-k file</code></td> <td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td> </tr> <tr> <td><code>-p file</code></td> <td>检测文件是否是有名管道,如果是,则返回true。</td> </tr> <tr> <td><code>-u file</code></td> <td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-r file</code></td> <td>检测文件是否可读,如果是,则返回true。</td> </tr> <tr> <td><code>-w file</code></td> <td>检测文件是否可写,如果是,则返回true。</td> </tr> <tr> <td><code>-x file</code></td> <td>检测文件是否可执行,如果是,则返回true。</td> </tr> <tr> <td><code>-s file</code></td> <td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td> </tr> <tr> <td><code>-e file</code></td> <td>检测文件(包括目录)是否存在,如果是,则返回true。</td> </tr> </tbody></table> <pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # file if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # directory if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi # not exist </code></pre> <h1>5. 数组</h1> <p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p> <ul> <li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li> <li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li> <li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li> </ul> <pre><code class="language-shell">arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&#39;new_value3&#39; echo $arr[3] # new_value3 echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]} # 4 echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; # arr[1]的长度为:6 </code></pre> <h1>6. 运算符</h1> <h2>6.1. 赋值运算符</h2> <pre><code class="language-shell">a=10 b=$a </code></pre> <h2>6.2. 算术运算符</h2> <p>算数运算符支持<code>+,-,*,/,%</code></p> <h3>6.2.1. expr表示法</h3> <pre><code class="language-shell">echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 </code></pre> <blockquote> <p>使用expr表示方法时,表达式和运算符之间必须有空格。</p> </blockquote> <h3>6.2.2. <code>$[]</code></h3> <pre><code class="language-shell">echo $[10%3] # 1 </code></pre> <h3>6.2.3. <code>$(())</code></h3> <pre><code class="language-shell">echo $((10*20)) # 200 </code></pre> <h2>6.3. 关系运算符</h2> <p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p> <pre><code class="language-shell">echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&gt;=10] # 1 </code></pre> <p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p> <blockquote> <p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p> </blockquote> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>-eq</code></td> <td>检测两个数是否相等,相等返回true。</td> <td><code>[ $a -eq $b ]</code></td> </tr> <tr> <td><code>-ne</code></td> <td>检测两个数是否不相等,不相等返回 true。</td> <td><code>[ $a -ne $b ]</code></td> </tr> <tr> <td><code>-gt</code></td> <td>检测左边的数是否大于右边的,如果是,则返回 true。</td> <td><code>[ $a -gt $b ]</code></td> </tr> <tr> <td><code>-lt</code></td> <td>检测左边的数是否小于右边的,如果是,则返回 true。</td> <td><code>[ $a -lt $b ]</code></td> </tr> <tr> <td><code>-ge</code></td> <td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -ge $b ]</code></td> </tr> <tr> <td><code>-le</code></td> <td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -le $b ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi; # hello if ((10&gt;=10));then echo &#39;hello&#39;;fi; # hello </code></pre> <h2>6.4. 布尔、逻辑运算符</h2> <p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>!</code></td> <td>非运算,表达式为true则返回false,否则返回true。</td> <td><code>[ ! 10 -eq 0 ]</code></td> </tr> <tr> <td><code>-o</code></td> <td>或运算,有一个表达式为true则返回true。</td> <td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td> </tr> <tr> <td><code>-a</code></td> <td>与运算,两个表达式都为true才返回true。</td> <td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi # hello </code></pre> <p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p> <pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi # hello if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi # hello </code></pre> <h1>7. 传递参数</h1> <p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p> <table> <thead> <tr> <th>参数处理</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>$#</code></td> <td>传递到脚本的参数个数</td> </tr> <tr> <td><code>$*</code></td> <td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$</code></td> <td>脚本运行的当前进程ID号</td> </tr> <tr> <td><code>$!</code></td> <td>后台运行的最后一个进程的ID号</td> </tr> <tr> <td><code>$@</code></td> <td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$-</code></td> <td>显示Shell使用的当前选项,与set功能相同。</td> </tr> <tr> <td><code>$?</code></td> <td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td> </tr> </tbody></table> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-bash">set -e echo &quot;执行的文件名:$0&quot; echo &quot;参数个数为$#&quot; echo &quot;第一个参数为:$1&quot; echo &quot;第二个参数为:$2&quot; echo &quot;所有参数为:$@&quot; echo &quot;进程ID号为:$&quot; echo &quot;当前shell选项为$-&quot; echo &quot;上一个命令退出的状态为$?&quot; </code></pre> <p>执行结果如下:</p> <pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 </code></pre> <h1>8. 函数</h1> <p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-shell">sayhello(){ echo &quot;hello&quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &quot;hello, $1 $2 $3&quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? </code></pre> <p>输出如下:</p> <blockquote> <p>hello<br>hello, zhangsan lisi wangwu<br>1</p> </blockquote> <h1>9. 命令替换</h1> <p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p> <pre><code class="language-shell"># command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 </code></pre> <h1>10. let命令</h1> <p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p> <ul> <li>自加操作:<code>let no++</code></li> <li>自减操作:<code>let no--</code></li> <li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li> </ul> <h1>11. 流程控制</h1> <h2>11.1. if</h2> <pre><code class="language-shell">if ((10&lt;2));then echo &quot;10小于2&quot; elif ((10&gt;20));then echo &quot;a大于10&quot; else echo &quot;10大于2且小于10&quot; fi </code></pre> <h2>11.2. case</h2> <p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p> <pre><code class="language-shell">case 10 in 0|1) echo &quot;a为0或1&quot; ;; 11|12) echo &quot;a为11或12&quot; ;; *) # *用来匹配所有情况 echo &quot;a为10&quot; ;; esac </code></pre> <h2>11.3. while</h2> <pre><code class="language-shell">count=0 while(($count&lt;5)) do echo $count let count++ done </code></pre> <h2>11.4. util</h2> <pre><code class="language-shell">count=0 until(($count&gt;=5)) do echo $count let count++ done </code></pre> <h2>11.5. for</h2> <pre><code class="language-shell"># for写法1 for ((count=0;$count&lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done </code></pre> <h2>11.6. break和continue</h2> <p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p> <pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1)) do     if (($count&gt;=5));then         break;     fi     echo $count done </code></pre> <h1>12. 输入输出重定向</h1> <h2>12.1. 输出重定向</h2> <p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p> <pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看 who &gt; users # 将字符串hello world保存到text.txt文件中 echo &quot;hello world&quot; &gt; text.txt </code></pre> <h2>12.2. 输入重定向</h2> <p><code>command &lt; file</code>从file文件获取输入</p> <pre><code class="language-shell">wc -l /etc/passwd # 123 /etc/passwd wc -l &lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &lt; /etc/passwd &gt; result cat result # 123 </code></pre> <h2>12.3. 文件描述符</h2> <p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p> <ul> <li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li> <li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li> <li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li> </ul> <pre><code class="language-shell"># 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;&gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &gt; result 2&gt;&amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&gt;result 2&gt;error_trace </code></pre> <h2>12.4. Here Document</h2> <p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p> <pre><code class="language-bash"># command &lt;&lt; EOF # document # EOF cat &lt;&lt; EOF hello shinerio learn shell EOF </code></pre> <blockquote> <p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p> </blockquote> <h2>12.5. /dev/null</h2> <p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p> <pre><code class="language-shell">cat users &gt; /dev/null cat users &gt; /dev/null 2&gt;&amp;1 </code></pre> <h1>13. set命令</h1> <p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p> <ul> <li>-e  若指令传回值不等于0,则立即退出shell。</li> <li>-f  取消使用通配符。</li> <li>-n  只读取指令,而不实际执行。</li> <li>-x  执行指令后,会先显示该指令及所下的参数。</li> </ul> </section> </article>lt;/code></td> <td>检测字符串是否为空,不为空返回true</td> <td><code>[ <article> <header> <h1>shell编程</h1> <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time> <div class="tags"> <span class="tag">linux</span> </div> </header> <section class="content"> <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p> <h1>1. 注释</h1> <h2>1.1. 单行注释</h2> <pre><code class="language-shell"># 这是单行注释 </code></pre> <h2>1.2. 多行注释</h2> <pre><code class="language-shell">:&lt;&lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF </code></pre> <p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p> <pre><code class="language-shell">:&lt;&lt;&#39; 多行注释内容 多行注释内容 多行注释内容 &#39; :&lt;&lt;! 多行注释内容 多行注释内容 多行注释内容 ! </code></pre> <h1>2. 变量</h1> <h2>2.1. 变量定义</h2> <p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p> <h2>2.2. 变量使用</h2> <p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p> <pre><code class="language-shell">your_age=25 your_name=&quot;shinerio&quot; your_name=shinerio your_name=&#39;shinerio&#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello} str=&#39;hello&#39;&#39; # 非法 str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接 echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt; str1=&#39;helloworld${your_age}\nnew line&#39; str2=&quot;helloworld${your_age}\nnew line&quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt; &lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line </code></pre> <h2>2.3. 只读变量</h2> <p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p> <pre><code class="language-shell">readonly name=&#39;jack&#39; name=&#39;kelly&#39; zsh: read-only variable: name </code></pre> <h2>2.4. 删除变量</h2> <p>使用<code>unset VARIABLENAME</code>删除变量。</p> <h1>3. 字符串操作</h1> <h2>3.1. 字符串拼接</h2> <pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot; str2=&quot;hello${your_name}world&quot; str3=&#39;hello&#39;${your_name}&#39;world&#39; </code></pre> <h2>3.2. 字符串长度</h2> <pre><code class="language-shell">str=&#39;hello&#39; echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;} 5 </code></pre> <h2>3.3. 字符串截取</h2> <p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p> <pre><code class="language-shell">str=&#39;helloworld&#39; echo ${str:0:5} hello </code></pre> <h2>3.4. 字符串运算符</h2> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>=</code></td> <td>检测两个字符串是否相等,相等返回true</td> <td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>!=</code></td> <td>检测两个字符串是否相等,不相等返回true</td> <td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td> </tr> <tr> <td><code>-z</code></td> <td>检测字符串长度是否为0,为0返回true</td> <td><code>[ -z &#39;&#39; ]</code></td> </tr> <tr> <td><code>-n </code></td> <td>检测字符串长度是否不为0,不为0返回true</td> <td><code>[ -n &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>$</code></td> <td>检测字符串是否为空,不为空返回true</td> <td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi # hello if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi # hello if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ];then echo &#39;hello&#39;;fi str=&#39;hello&#39; if [ $str ];then echo &#39;hello&#39;;fi # hello </code></pre> <p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p> <h1>4. 文件测试运算符</h1> <table> <thead> <tr> <th>操作符</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>-b file</code></td> <td>检测文件是否是块设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-c file</code></td> <td>检测文件是否是字符设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-d file</code></td> <td>检测文件是否是目录,如果是,则返回true。</td> </tr> <tr> <td><code>-f file</code></td> <td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td> </tr> <tr> <td><code>-g file</code></td> <td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-k file</code></td> <td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td> </tr> <tr> <td><code>-p file</code></td> <td>检测文件是否是有名管道,如果是,则返回true。</td> </tr> <tr> <td><code>-u file</code></td> <td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-r file</code></td> <td>检测文件是否可读,如果是,则返回true。</td> </tr> <tr> <td><code>-w file</code></td> <td>检测文件是否可写,如果是,则返回true。</td> </tr> <tr> <td><code>-x file</code></td> <td>检测文件是否可执行,如果是,则返回true。</td> </tr> <tr> <td><code>-s file</code></td> <td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td> </tr> <tr> <td><code>-e file</code></td> <td>检测文件(包括目录)是否存在,如果是,则返回true。</td> </tr> </tbody></table> <pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # file if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # directory if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi # not exist </code></pre> <h1>5. 数组</h1> <p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p> <ul> <li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li> <li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li> <li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li> </ul> <pre><code class="language-shell">arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&#39;new_value3&#39; echo $arr[3] # new_value3 echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]} # 4 echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; # arr[1]的长度为:6 </code></pre> <h1>6. 运算符</h1> <h2>6.1. 赋值运算符</h2> <pre><code class="language-shell">a=10 b=$a </code></pre> <h2>6.2. 算术运算符</h2> <p>算数运算符支持<code>+,-,*,/,%</code></p> <h3>6.2.1. expr表示法</h3> <pre><code class="language-shell">echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 </code></pre> <blockquote> <p>使用expr表示方法时,表达式和运算符之间必须有空格。</p> </blockquote> <h3>6.2.2. <code>$[]</code></h3> <pre><code class="language-shell">echo $[10%3] # 1 </code></pre> <h3>6.2.3. <code>$(())</code></h3> <pre><code class="language-shell">echo $((10*20)) # 200 </code></pre> <h2>6.3. 关系运算符</h2> <p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p> <pre><code class="language-shell">echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&gt;=10] # 1 </code></pre> <p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p> <blockquote> <p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p> </blockquote> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>-eq</code></td> <td>检测两个数是否相等,相等返回true。</td> <td><code>[ $a -eq $b ]</code></td> </tr> <tr> <td><code>-ne</code></td> <td>检测两个数是否不相等,不相等返回 true。</td> <td><code>[ $a -ne $b ]</code></td> </tr> <tr> <td><code>-gt</code></td> <td>检测左边的数是否大于右边的,如果是,则返回 true。</td> <td><code>[ $a -gt $b ]</code></td> </tr> <tr> <td><code>-lt</code></td> <td>检测左边的数是否小于右边的,如果是,则返回 true。</td> <td><code>[ $a -lt $b ]</code></td> </tr> <tr> <td><code>-ge</code></td> <td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -ge $b ]</code></td> </tr> <tr> <td><code>-le</code></td> <td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -le $b ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi; # hello if ((10&gt;=10));then echo &#39;hello&#39;;fi; # hello </code></pre> <h2>6.4. 布尔、逻辑运算符</h2> <p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>!</code></td> <td>非运算,表达式为true则返回false,否则返回true。</td> <td><code>[ ! 10 -eq 0 ]</code></td> </tr> <tr> <td><code>-o</code></td> <td>或运算,有一个表达式为true则返回true。</td> <td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td> </tr> <tr> <td><code>-a</code></td> <td>与运算,两个表达式都为true才返回true。</td> <td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi # hello </code></pre> <p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p> <pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi # hello if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi # hello </code></pre> <h1>7. 传递参数</h1> <p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p> <table> <thead> <tr> <th>参数处理</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>$#</code></td> <td>传递到脚本的参数个数</td> </tr> <tr> <td><code>$*</code></td> <td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$</code></td> <td>脚本运行的当前进程ID号</td> </tr> <tr> <td><code>$!</code></td> <td>后台运行的最后一个进程的ID号</td> </tr> <tr> <td><code>$@</code></td> <td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$-</code></td> <td>显示Shell使用的当前选项,与set功能相同。</td> </tr> <tr> <td><code>$?</code></td> <td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td> </tr> </tbody></table> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-bash">set -e echo &quot;执行的文件名:$0&quot; echo &quot;参数个数为$#&quot; echo &quot;第一个参数为:$1&quot; echo &quot;第二个参数为:$2&quot; echo &quot;所有参数为:$@&quot; echo &quot;进程ID号为:$&quot; echo &quot;当前shell选项为$-&quot; echo &quot;上一个命令退出的状态为$?&quot; </code></pre> <p>执行结果如下:</p> <pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 </code></pre> <h1>8. 函数</h1> <p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-shell">sayhello(){ echo &quot;hello&quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &quot;hello, $1 $2 $3&quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? </code></pre> <p>输出如下:</p> <blockquote> <p>hello<br>hello, zhangsan lisi wangwu<br>1</p> </blockquote> <h1>9. 命令替换</h1> <p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p> <pre><code class="language-shell"># command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 </code></pre> <h1>10. let命令</h1> <p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p> <ul> <li>自加操作:<code>let no++</code></li> <li>自减操作:<code>let no--</code></li> <li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li> </ul> <h1>11. 流程控制</h1> <h2>11.1. if</h2> <pre><code class="language-shell">if ((10&lt;2));then echo &quot;10小于2&quot; elif ((10&gt;20));then echo &quot;a大于10&quot; else echo &quot;10大于2且小于10&quot; fi </code></pre> <h2>11.2. case</h2> <p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p> <pre><code class="language-shell">case 10 in 0|1) echo &quot;a为0或1&quot; ;; 11|12) echo &quot;a为11或12&quot; ;; *) # *用来匹配所有情况 echo &quot;a为10&quot; ;; esac </code></pre> <h2>11.3. while</h2> <pre><code class="language-shell">count=0 while(($count&lt;5)) do echo $count let count++ done </code></pre> <h2>11.4. util</h2> <pre><code class="language-shell">count=0 until(($count&gt;=5)) do echo $count let count++ done </code></pre> <h2>11.5. for</h2> <pre><code class="language-shell"># for写法1 for ((count=0;$count&lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done </code></pre> <h2>11.6. break和continue</h2> <p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p> <pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1)) do     if (($count&gt;=5));then         break;     fi     echo $count done </code></pre> <h1>12. 输入输出重定向</h1> <h2>12.1. 输出重定向</h2> <p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p> <pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看 who &gt; users # 将字符串hello world保存到text.txt文件中 echo &quot;hello world&quot; &gt; text.txt </code></pre> <h2>12.2. 输入重定向</h2> <p><code>command &lt; file</code>从file文件获取输入</p> <pre><code class="language-shell">wc -l /etc/passwd # 123 /etc/passwd wc -l &lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &lt; /etc/passwd &gt; result cat result # 123 </code></pre> <h2>12.3. 文件描述符</h2> <p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p> <ul> <li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li> <li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li> <li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li> </ul> <pre><code class="language-shell"># 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;&gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &gt; result 2&gt;&amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&gt;result 2&gt;error_trace </code></pre> <h2>12.4. Here Document</h2> <p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p> <pre><code class="language-bash"># command &lt;&lt; EOF # document # EOF cat &lt;&lt; EOF hello shinerio learn shell EOF </code></pre> <blockquote> <p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p> </blockquote> <h2>12.5. /dev/null</h2> <p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p> <pre><code class="language-shell">cat users &gt; /dev/null cat users &gt; /dev/null 2&gt;&amp;1 </code></pre> <h1>13. set命令</h1> <p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p> <ul> <li>-e  若指令传回值不等于0,则立即退出shell。</li> <li>-f  取消使用通配符。</li> <li>-n  只读取指令,而不实际执行。</li> <li>-x  执行指令后,会先显示该指令及所下的参数。</li> </ul> </section> </article>amp;#39;hello&#39; ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi # hello if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi # hello if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ <article> <header> <h1>shell编程</h1> <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time> <div class="tags"> <span class="tag">linux</span> </div> </header> <section class="content"> <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p> <h1>1. 注释</h1> <h2>1.1. 单行注释</h2> <pre><code class="language-shell"># 这是单行注释 </code></pre> <h2>1.2. 多行注释</h2> <pre><code class="language-shell">:&lt;&lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF </code></pre> <p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p> <pre><code class="language-shell">:&lt;&lt;&#39; 多行注释内容 多行注释内容 多行注释内容 &#39; :&lt;&lt;! 多行注释内容 多行注释内容 多行注释内容 ! </code></pre> <h1>2. 变量</h1> <h2>2.1. 变量定义</h2> <p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p> <h2>2.2. 变量使用</h2> <p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p> <pre><code class="language-shell">your_age=25 your_name=&quot;shinerio&quot; your_name=shinerio your_name=&#39;shinerio&#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello} str=&#39;hello&#39;&#39; # 非法 str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接 echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt; str1=&#39;helloworld${your_age}\nnew line&#39; str2=&quot;helloworld${your_age}\nnew line&quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt; &lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line </code></pre> <h2>2.3. 只读变量</h2> <p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p> <pre><code class="language-shell">readonly name=&#39;jack&#39; name=&#39;kelly&#39; zsh: read-only variable: name </code></pre> <h2>2.4. 删除变量</h2> <p>使用<code>unset VARIABLENAME</code>删除变量。</p> <h1>3. 字符串操作</h1> <h2>3.1. 字符串拼接</h2> <pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot; str2=&quot;hello${your_name}world&quot; str3=&#39;hello&#39;${your_name}&#39;world&#39; </code></pre> <h2>3.2. 字符串长度</h2> <pre><code class="language-shell">str=&#39;hello&#39; echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;} 5 </code></pre> <h2>3.3. 字符串截取</h2> <p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p> <pre><code class="language-shell">str=&#39;helloworld&#39; echo ${str:0:5} hello </code></pre> <h2>3.4. 字符串运算符</h2> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>=</code></td> <td>检测两个字符串是否相等,相等返回true</td> <td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>!=</code></td> <td>检测两个字符串是否相等,不相等返回true</td> <td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td> </tr> <tr> <td><code>-z</code></td> <td>检测字符串长度是否为0,为0返回true</td> <td><code>[ -z &#39;&#39; ]</code></td> </tr> <tr> <td><code>-n </code></td> <td>检测字符串长度是否不为0,不为0返回true</td> <td><code>[ -n &#39;hello&#39; ]</code></td> </tr> <tr> <td><code>$</code></td> <td>检测字符串是否为空,不为空返回true</td> <td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi # hello if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi # hello if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi # hello if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt; &lt;h1&gt;1. 注释&lt;/h1&gt; &lt;h2&gt;1.1. 单行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;1.2. 多行注释&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF 多行注释内容 多行注释内容 多行注释内容 EOF &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39; 多行注释内容 多行注释内容 多行注释内容 &amp;#39; :&amp;lt;&amp;lt;! 多行注释内容 多行注释内容 多行注释内容 ! &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;2. 变量&lt;/h1&gt; &lt;h2&gt;2.1. 变量定义&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt; &lt;h2&gt;2.2. 变量使用&lt;/h2&gt; &lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25 your_name=&amp;quot;shinerio&amp;quot; your_name=shinerio your_name=&amp;#39;shinerio&amp;#39; echo $your_age # 输出25 echo $your_name # 输出shinerio echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello} str=&amp;#39;hello&amp;#39;&amp;#39; # 非法 str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接 echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt; str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39; str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot; echo $str1 # 输出helloworld${your_age}\nnew line echo $str2 # 输出helloworld25\nnew line echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行 &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.3. 只读变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39; name=&amp;#39;kelly&amp;#39; zsh: read-only variable: name &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;2.4. 删除变量&lt;/h2&gt; &lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt; &lt;h1&gt;3. 字符串操作&lt;/h1&gt; &lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot; str2=&amp;quot;hello${your_name}world&amp;quot; str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39; &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.2. 字符串长度&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39; echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;} 5 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.3. 字符串截取&lt;/h2&gt; &lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39; echo ${str:0:5} hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi str=&amp;#39;hello&amp;#39; if [ $str ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt; &lt;h1&gt;4. 文件测试运算符&lt;/h1&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;操作符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # file if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi # directory if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi # not exist &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;5. 数组&lt;/h1&gt; &lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt; &lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&amp;#39;new_value3&amp;#39; echo $arr[3] # new_value3 echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]} # 4 echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; # arr[1]的长度为:6 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;6. 运算符&lt;/h1&gt; &lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10 b=$a &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.2. 算术运算符&lt;/h2&gt; &lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt; &lt;/blockquote&gt; &lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20)) # 200 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.3. 关系运算符&lt;/h2&gt; &lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&amp;gt;=10] # 1 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt; &lt;/blockquote&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt; &lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi; # hello if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi; # hello &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt; &lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;运算符&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;th&gt;举例&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt; &lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt; &lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi # hello if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi # hello &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;7. 传递参数&lt;/h1&gt; &lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;参数处理&lt;/th&gt; &lt;th&gt;说明&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt; &lt;td&gt;传递到脚本的参数个数&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt; &lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt; &lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt; &lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt; &lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt; &lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e echo &amp;quot;执行的文件名:$0&amp;quot; echo &amp;quot;参数个数为$#&amp;quot; echo &amp;quot;第一个参数为:$1&amp;quot; echo &amp;quot;第二个参数为:$2&amp;quot; echo &amp;quot;所有参数为:$@&amp;quot; echo &amp;quot;进程ID号为:$$&amp;quot; echo &amp;quot;当前shell选项为$-&amp;quot; echo &amp;quot;上一个命令退出的状态为$?&amp;quot; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行结果如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;8. 函数&lt;/h1&gt; &lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt; &lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){ echo &amp;quot;hello&amp;quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &amp;quot;hello, $1 $2 $3&amp;quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;输出如下:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt; &lt;/blockquote&gt; &lt;h1&gt;9. 命令替换&lt;/h1&gt; &lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;10. let命令&lt;/h1&gt; &lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt; &lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt; &lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;11. 流程控制&lt;/h1&gt; &lt;h2&gt;11.1. if&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then echo &amp;quot;10小于2&amp;quot; elif ((10&amp;gt;20));then echo &amp;quot;a大于10&amp;quot; else echo &amp;quot;10大于2且小于10&amp;quot; fi &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.2. case&lt;/h2&gt; &lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in 0|1) echo &amp;quot;a为0或1&amp;quot; ;; 11|12) echo &amp;quot;a为11或12&amp;quot; ;; *) # *用来匹配所有情况 echo &amp;quot;a为10&amp;quot; ;; esac &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.3. while&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 while(($count&amp;lt;5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.4. util&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0 until(($count&amp;gt;=5)) do echo $count let count++ done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.5. for&lt;/h2&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1 for ((count=0;$count&amp;lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;11.6. break和continue&lt;/h2&gt; &lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1)) do     if (($count&amp;gt;=5));then         break;     fi     echo $count done &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;12. 输入输出重定向&lt;/h1&gt; &lt;h2&gt;12.1. 输出重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看 who &amp;gt; users # 将字符串hello world保存到text.txt文件中 echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.2. 输入重定向&lt;/h2&gt; &lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd # 123 /etc/passwd wc -l &amp;lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &amp;lt; /etc/passwd &amp;gt; result cat result # 123 &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.3. 文件描述符&lt;/h2&gt; &lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt; &lt;ul&gt; &lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt; &lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt; &lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&amp;gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;amp;&amp;gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace &lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;12.4. Here Document&lt;/h2&gt; &lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF # document # EOF cat &amp;lt;&amp;lt; EOF hello shinerio learn shell EOF &lt;/code&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt; &lt;/blockquote&gt; &lt;h2&gt;12.5. /dev/null&lt;/h2&gt; &lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;13. set命令&lt;/h1&gt; &lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt; &lt;li&gt;-f  取消使用通配符。&lt;/li&gt; &lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt; &lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt; &lt;/ul&gt; #39;hello&#39; ];then echo &#39;hello&#39;;fi str=&#39;hello&#39; if [ $str ];then echo &#39;hello&#39;;fi # hello </code></pre> <p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p> <h1>4. 文件测试运算符</h1> <table> <thead> <tr> <th>操作符</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>-b file</code></td> <td>检测文件是否是块设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-c file</code></td> <td>检测文件是否是字符设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-d file</code></td> <td>检测文件是否是目录,如果是,则返回true。</td> </tr> <tr> <td><code>-f file</code></td> <td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td> </tr> <tr> <td><code>-g file</code></td> <td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-k file</code></td> <td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td> </tr> <tr> <td><code>-p file</code></td> <td>检测文件是否是有名管道,如果是,则返回true。</td> </tr> <tr> <td><code>-u file</code></td> <td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-r file</code></td> <td>检测文件是否可读,如果是,则返回true。</td> </tr> <tr> <td><code>-w file</code></td> <td>检测文件是否可写,如果是,则返回true。</td> </tr> <tr> <td><code>-x file</code></td> <td>检测文件是否可执行,如果是,则返回true。</td> </tr> <tr> <td><code>-s file</code></td> <td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td> </tr> <tr> <td><code>-e file</code></td> <td>检测文件(包括目录)是否存在,如果是,则返回true。</td> </tr> </tbody></table> <pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # file if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # directory if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi # not exist </code></pre> <h1>5. 数组</h1> <p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p> <ul> <li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li> <li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li> <li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li> </ul> <pre><code class="language-shell">arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&#39;new_value3&#39; echo $arr[3] # new_value3 echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]} # 4 echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; # arr[1]的长度为:6 </code></pre> <h1>6. 运算符</h1> <h2>6.1. 赋值运算符</h2> <pre><code class="language-shell">a=10 b=$a </code></pre> <h2>6.2. 算术运算符</h2> <p>算数运算符支持<code>+,-,*,/,%</code></p> <h3>6.2.1. expr表示法</h3> <pre><code class="language-shell">echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 </code></pre> <blockquote> <p>使用expr表示方法时,表达式和运算符之间必须有空格。</p> </blockquote> <h3>6.2.2. <code>$[]</code></h3> <pre><code class="language-shell">echo $[10%3] # 1 </code></pre> <h3>6.2.3. <code>$(())</code></h3> <pre><code class="language-shell">echo $((10*20)) # 200 </code></pre> <h2>6.3. 关系运算符</h2> <p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p> <pre><code class="language-shell">echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&gt;=10] # 1 </code></pre> <p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p> <blockquote> <p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p> </blockquote> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>-eq</code></td> <td>检测两个数是否相等,相等返回true。</td> <td><code>[ $a -eq $b ]</code></td> </tr> <tr> <td><code>-ne</code></td> <td>检测两个数是否不相等,不相等返回 true。</td> <td><code>[ $a -ne $b ]</code></td> </tr> <tr> <td><code>-gt</code></td> <td>检测左边的数是否大于右边的,如果是,则返回 true。</td> <td><code>[ $a -gt $b ]</code></td> </tr> <tr> <td><code>-lt</code></td> <td>检测左边的数是否小于右边的,如果是,则返回 true。</td> <td><code>[ $a -lt $b ]</code></td> </tr> <tr> <td><code>-ge</code></td> <td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -ge $b ]</code></td> </tr> <tr> <td><code>-le</code></td> <td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -le $b ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi; # hello if ((10&gt;=10));then echo &#39;hello&#39;;fi; # hello </code></pre> <h2>6.4. 布尔、逻辑运算符</h2> <p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>!</code></td> <td>非运算,表达式为true则返回false,否则返回true。</td> <td><code>[ ! 10 -eq 0 ]</code></td> </tr> <tr> <td><code>-o</code></td> <td>或运算,有一个表达式为true则返回true。</td> <td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td> </tr> <tr> <td><code>-a</code></td> <td>与运算,两个表达式都为true才返回true。</td> <td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi # hello </code></pre> <p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p> <pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi # hello if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi # hello </code></pre> <h1>7. 传递参数</h1> <p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p> <table> <thead> <tr> <th>参数处理</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>$#</code></td> <td>传递到脚本的参数个数</td> </tr> <tr> <td><code>$*</code></td> <td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$</code></td> <td>脚本运行的当前进程ID号</td> </tr> <tr> <td><code>$!</code></td> <td>后台运行的最后一个进程的ID号</td> </tr> <tr> <td><code>$@</code></td> <td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$-</code></td> <td>显示Shell使用的当前选项,与set功能相同。</td> </tr> <tr> <td><code>$?</code></td> <td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td> </tr> </tbody></table> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-bash">set -e echo &quot;执行的文件名:$0&quot; echo &quot;参数个数为$#&quot; echo &quot;第一个参数为:$1&quot; echo &quot;第二个参数为:$2&quot; echo &quot;所有参数为:$@&quot; echo &quot;进程ID号为:$&quot; echo &quot;当前shell选项为$-&quot; echo &quot;上一个命令退出的状态为$?&quot; </code></pre> <p>执行结果如下:</p> <pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 </code></pre> <h1>8. 函数</h1> <p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-shell">sayhello(){ echo &quot;hello&quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &quot;hello, $1 $2 $3&quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? </code></pre> <p>输出如下:</p> <blockquote> <p>hello<br>hello, zhangsan lisi wangwu<br>1</p> </blockquote> <h1>9. 命令替换</h1> <p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p> <pre><code class="language-shell"># command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 </code></pre> <h1>10. let命令</h1> <p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p> <ul> <li>自加操作:<code>let no++</code></li> <li>自减操作:<code>let no--</code></li> <li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li> </ul> <h1>11. 流程控制</h1> <h2>11.1. if</h2> <pre><code class="language-shell">if ((10&lt;2));then echo &quot;10小于2&quot; elif ((10&gt;20));then echo &quot;a大于10&quot; else echo &quot;10大于2且小于10&quot; fi </code></pre> <h2>11.2. case</h2> <p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p> <pre><code class="language-shell">case 10 in 0|1) echo &quot;a为0或1&quot; ;; 11|12) echo &quot;a为11或12&quot; ;; *) # *用来匹配所有情况 echo &quot;a为10&quot; ;; esac </code></pre> <h2>11.3. while</h2> <pre><code class="language-shell">count=0 while(($count&lt;5)) do echo $count let count++ done </code></pre> <h2>11.4. util</h2> <pre><code class="language-shell">count=0 until(($count&gt;=5)) do echo $count let count++ done </code></pre> <h2>11.5. for</h2> <pre><code class="language-shell"># for写法1 for ((count=0;$count&lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done </code></pre> <h2>11.6. break和continue</h2> <p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p> <pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1)) do     if (($count&gt;=5));then         break;     fi     echo $count done </code></pre> <h1>12. 输入输出重定向</h1> <h2>12.1. 输出重定向</h2> <p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p> <pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看 who &gt; users # 将字符串hello world保存到text.txt文件中 echo &quot;hello world&quot; &gt; text.txt </code></pre> <h2>12.2. 输入重定向</h2> <p><code>command &lt; file</code>从file文件获取输入</p> <pre><code class="language-shell">wc -l /etc/passwd # 123 /etc/passwd wc -l &lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &lt; /etc/passwd &gt; result cat result # 123 </code></pre> <h2>12.3. 文件描述符</h2> <p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p> <ul> <li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li> <li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li> <li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li> </ul> <pre><code class="language-shell"># 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;&gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &gt; result 2&gt;&amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&gt;result 2&gt;error_trace </code></pre> <h2>12.4. Here Document</h2> <p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p> <pre><code class="language-bash"># command &lt;&lt; EOF # document # EOF cat &lt;&lt; EOF hello shinerio learn shell EOF </code></pre> <blockquote> <p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p> </blockquote> <h2>12.5. /dev/null</h2> <p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p> <pre><code class="language-shell">cat users &gt; /dev/null cat users &gt; /dev/null 2&gt;&amp;1 </code></pre> <h1>13. set命令</h1> <p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p> <ul> <li>-e  若指令传回值不等于0,则立即退出shell。</li> <li>-f  取消使用通配符。</li> <li>-n  只读取指令,而不实际执行。</li> <li>-x  执行指令后,会先显示该指令及所下的参数。</li> </ul> </section> </article>amp;#39;hello&#39; ];then echo &#39;hello&#39;;fi str=&#39;hello&#39; if [ $str ];then echo &#39;hello&#39;;fi # hello </code></pre> <p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p> <h1>4. 文件测试运算符</h1> <table> <thead> <tr> <th>操作符</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>-b file</code></td> <td>检测文件是否是块设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-c file</code></td> <td>检测文件是否是字符设备文件,如果是,则返回true。</td> </tr> <tr> <td><code>-d file</code></td> <td>检测文件是否是目录,如果是,则返回true。</td> </tr> <tr> <td><code>-f file</code></td> <td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td> </tr> <tr> <td><code>-g file</code></td> <td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-k file</code></td> <td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td> </tr> <tr> <td><code>-p file</code></td> <td>检测文件是否是有名管道,如果是,则返回true。</td> </tr> <tr> <td><code>-u file</code></td> <td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td> </tr> <tr> <td><code>-r file</code></td> <td>检测文件是否可读,如果是,则返回true。</td> </tr> <tr> <td><code>-w file</code></td> <td>检测文件是否可写,如果是,则返回true。</td> </tr> <tr> <td><code>-x file</code></td> <td>检测文件是否可执行,如果是,则返回true。</td> </tr> <tr> <td><code>-s file</code></td> <td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td> </tr> <tr> <td><code>-e file</code></td> <td>检测文件(包括目录)是否存在,如果是,则返回true。</td> </tr> </tbody></table> <pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # file if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi # directory if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi # not exist </code></pre> <h1>5. 数组</h1> <p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p> <ul> <li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li> <li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li> <li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li> </ul> <pre><code class="language-shell">arr=(value1 value2 value3 value4) echo ${arr[3]} # value3 echo ${arr[*]} # value1 value2 value3 value4 echo ${arr[@]} # value1 value2 value3 value4 arr[3]=&#39;new_value3&#39; echo $arr[3] # new_value3 echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]} # 4 echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; # arr[1]的长度为:6 </code></pre> <h1>6. 运算符</h1> <h2>6.1. 赋值运算符</h2> <pre><code class="language-shell">a=10 b=$a </code></pre> <h2>6.2. 算术运算符</h2> <p>算数运算符支持<code>+,-,*,/,%</code></p> <h3>6.2.1. expr表示法</h3> <pre><code class="language-shell">echo `expr 10 + 20` # 30 echo $(expr 20 / 2) # 10 echo $(expr 10 \* 20) # 使用expr进行乘法运算时必须使用\进行转义 # 200 </code></pre> <blockquote> <p>使用expr表示方法时,表达式和运算符之间必须有空格。</p> </blockquote> <h3>6.2.2. <code>$[]</code></h3> <pre><code class="language-shell">echo $[10%3] # 1 </code></pre> <h3>6.2.3. <code>$(())</code></h3> <pre><code class="language-shell">echo $((10*20)) # 200 </code></pre> <h2>6.3. 关系运算符</h2> <p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p> <pre><code class="language-shell">echo $[10==10] # 1 flag=$[20==10] echo $flag # 1 echo $[10&gt;=10] # 1 </code></pre> <p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p> <blockquote> <p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p> </blockquote> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>-eq</code></td> <td>检测两个数是否相等,相等返回true。</td> <td><code>[ $a -eq $b ]</code></td> </tr> <tr> <td><code>-ne</code></td> <td>检测两个数是否不相等,不相等返回 true。</td> <td><code>[ $a -ne $b ]</code></td> </tr> <tr> <td><code>-gt</code></td> <td>检测左边的数是否大于右边的,如果是,则返回 true。</td> <td><code>[ $a -gt $b ]</code></td> </tr> <tr> <td><code>-lt</code></td> <td>检测左边的数是否小于右边的,如果是,则返回 true。</td> <td><code>[ $a -lt $b ]</code></td> </tr> <tr> <td><code>-ge</code></td> <td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -ge $b ]</code></td> </tr> <tr> <td><code>-le</code></td> <td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td> <td><code>[ $a -le $b ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi; # hello if ((10&gt;=10));then echo &#39;hello&#39;;fi; # hello </code></pre> <h2>6.4. 布尔、逻辑运算符</h2> <p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p> <table> <thead> <tr> <th>运算符</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody><tr> <td><code>!</code></td> <td>非运算,表达式为true则返回false,否则返回true。</td> <td><code>[ ! 10 -eq 0 ]</code></td> </tr> <tr> <td><code>-o</code></td> <td>或运算,有一个表达式为true则返回true。</td> <td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td> </tr> <tr> <td><code>-a</code></td> <td>与运算,两个表达式都为true才返回true。</td> <td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td> </tr> </tbody></table> <pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi # hello if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi # hello </code></pre> <p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p> <pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi # hello if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi # hello </code></pre> <h1>7. 传递参数</h1> <p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p> <table> <thead> <tr> <th>参数处理</th> <th>说明</th> </tr> </thead> <tbody><tr> <td><code>$#</code></td> <td>传递到脚本的参数个数</td> </tr> <tr> <td><code>$*</code></td> <td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$</code></td> <td>脚本运行的当前进程ID号</td> </tr> <tr> <td><code>$!</code></td> <td>后台运行的最后一个进程的ID号</td> </tr> <tr> <td><code>$@</code></td> <td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td> </tr> <tr> <td><code>$-</code></td> <td>显示Shell使用的当前选项,与set功能相同。</td> </tr> <tr> <td><code>$?</code></td> <td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td> </tr> </tbody></table> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-bash">set -e echo &quot;执行的文件名:$0&quot; echo &quot;参数个数为$#&quot; echo &quot;第一个参数为:$1&quot; echo &quot;第二个参数为:$2&quot; echo &quot;所有参数为:$@&quot; echo &quot;进程ID号为:$&quot; echo &quot;当前shell选项为$-&quot; echo &quot;上一个命令退出的状态为$?&quot; </code></pre> <p>执行结果如下:</p> <pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot; 执行的文件名:test.sh 参数个数为2 第一个参数为:param1 第二个参数为:param2 with space 所有参数为:param1 param2 with space 进程ID号为:3700 当前shell选项为ehB 上一个命令退出的状态为0 </code></pre> <h1>8. 函数</h1> <p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p> <p>编写<code>shell</code>脚本如下:</p> <pre><code class="language-shell">sayhello(){ echo &quot;hello&quot; } # 注意函数调用只需要函数名,不需要加() sayhello sayhellowithparam(){ echo &quot;hello, $1 $2 $3&quot; return 1 } sayhellowithparam zhangsan lisi wangwu echo $? </code></pre> <p>输出如下:</p> <blockquote> <p>hello<br>hello, zhangsan lisi wangwu<br>1</p> </blockquote> <h1>9. 命令替换</h1> <p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p> <pre><code class="language-shell"># command1 `command2` cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下 cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录 </code></pre> <h1>10. let命令</h1> <p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p> <ul> <li>自加操作:<code>let no++</code></li> <li>自减操作:<code>let no--</code></li> <li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li> </ul> <h1>11. 流程控制</h1> <h2>11.1. if</h2> <pre><code class="language-shell">if ((10&lt;2));then echo &quot;10小于2&quot; elif ((10&gt;20));then echo &quot;a大于10&quot; else echo &quot;10大于2且小于10&quot; fi </code></pre> <h2>11.2. case</h2> <p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p> <pre><code class="language-shell">case 10 in 0|1) echo &quot;a为0或1&quot; ;; 11|12) echo &quot;a为11或12&quot; ;; *) # *用来匹配所有情况 echo &quot;a为10&quot; ;; esac </code></pre> <h2>11.3. while</h2> <pre><code class="language-shell">count=0 while(($count&lt;5)) do echo $count let count++ done </code></pre> <h2>11.4. util</h2> <pre><code class="language-shell">count=0 until(($count&gt;=5)) do echo $count let count++ done </code></pre> <h2>11.5. for</h2> <pre><code class="language-shell"># for写法1 for ((count=0;$count&lt;5;count=$count+1)) do echo $count done # for写法2 arr=(0 1 2 3 4) for count in ${arr[*]} do echo $int done # for写法3 for int in 0 1 2 3 4 do echo $int done </code></pre> <h2>11.6. break和continue</h2> <p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p> <pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1)) do     if (($count&gt;=5));then         break;     fi     echo $count done </code></pre> <h1>12. 输入输出重定向</h1> <h2>12.1. 输出重定向</h2> <p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p> <pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看 who &gt; users # 将字符串hello world保存到text.txt文件中 echo &quot;hello world&quot; &gt; text.txt </code></pre> <h2>12.2. 输入重定向</h2> <p><code>command &lt; file</code>从file文件获取输入</p> <pre><code class="language-shell">wc -l /etc/passwd # 123 /etc/passwd wc -l &lt; users # 123 # 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容 # command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。 wc -l &lt; /etc/passwd &gt; result cat result # 123 </code></pre> <h2>12.3. 文件描述符</h2> <p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p> <ul> <li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li> <li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li> <li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li> </ul> <pre><code class="language-shell"># 将标准错误输出重定向到error_trace cat /tmp/fake_file 2&gt;error_trace cat error_trace # cat: /tmp/fake_fule: No such file or directory # 将标准输出和标准错误输出都重定向到result cat /tmp/fake_file &amp;&gt;result cat result # cat: /tmp/fake_fule: No such file or directory # 将标准错误重定向到标准输出 ls /tmp/fake_file &gt; result 2&gt;&amp;1 cat result # cat: /tmp/fake_fule: No such file or directory # 将标准输入重定向到result,将标准错误输出重定向到error_trace cat /tmp/fake_file 1&gt;result 2&gt;error_trace </code></pre> <h2>12.4. Here Document</h2> <p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p> <pre><code class="language-bash"># command &lt;&lt; EOF # document # EOF cat &lt;&lt; EOF hello shinerio learn shell EOF </code></pre> <blockquote> <p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p> </blockquote> <h2>12.5. /dev/null</h2> <p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p> <pre><code class="language-shell">cat users &gt; /dev/null cat users &gt; /dev/null 2&gt;&amp;1 </code></pre> <h1>13. set命令</h1> <p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p> <ul> <li>-e  若指令传回值不等于0,则立即退出shell。</li> <li>-f  取消使用通配符。</li> <li>-n  只读取指令,而不实际执行。</li> <li>-x  执行指令后,会先显示该指令及所下的参数。</li> </ul> #39;hello' ]
if [ 'hello' = 'hello' ];then echo 'hello';fi
# hello
if [ 'hello' != 'ello' ];then echo 'hello';fi
# hello
if [ -z '' ];then echo 'hello';fi
# hello
if [ -n 'hello' ];then echo 'hello';fi
# hello
if [ <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code><article>
    <header>
        <h1>shell编程</h1>
        <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time>
        <div class="tags">
            
            <span class="tag">linux</span>
            
        </div>
    </header>
    <section class="content">
        <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>$</code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>

    </section>
</article>lt;/code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code><article>
    <header>
        <h1>shell编程</h1>
        <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time>
        <div class="tags">
            
            <span class="tag">linux</span>
            
        </div>
    </header>
    <section class="content">
        <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>$</code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>

    </section>
</article>lt;/code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ <article>
    <header>
        <h1>shell编程</h1>
        <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time>
        <div class="tags">
            
            <span class="tag">linux</span>
            
        </div>
    </header>
    <section class="content">
        <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>$</code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>

    </section>
</article>amp;#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ <article>
    <header>
        <h1>shell编程</h1>
        <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time>
        <div class="tags">
            
            <span class="tag">linux</span>
            
        </div>
    </header>
    <section class="content">
        <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>$</code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>

    </section>
</article>amp;#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>
#39;hello' ];then echo 'hello';fi
str='hello'
if [ $str ];then echo 'hello';fi
# hello

注意字符串的等值判断是一个等号"=",与下文要讲的逻辑运算符使用两个等号"=="做等值判断不一样。

4. 文件测试运算符

操作符 说明
-b file 检测文件是否是块设备文件,如果是,则返回true。
-c file 检测文件是否是字符设备文件,如果是,则返回true。
-d file 检测文件是否是目录,如果是,则返回true。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。
-g file 检测文件是否设置了SGID位,如果是,则返回true。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。
-p file 检测文件是否是有名管道,如果是,则返回true。
-u file 检测文件是否设置了SUID位,如果是,则返回true。
-r file 检测文件是否可读,如果是,则返回true。
-w file 检测文件是否可写,如果是,则返回true。
-x file 检测文件是否可执行,如果是,则返回true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回true。
-e file 检测文件(包括目录)是否存在,如果是,则返回true。
if <a href="f-home.html" class="internal-link"> -f '/home' </a>;then echo 'directory';else echo 'file';fi
# file
if <a href="d-home.html" class="internal-link"> -d '/home' </a>;then echo 'directory';else echo 'file';fi
# directory
if <a href="e-tmpfake-file.html" class="internal-link"> -e '/tmp/fake_file' </a>;then echo 'exist';else echo 'not exist';fi
# not exist

5. 数组

shell只支持一维数组,用括号表示,元素通过空格分隔,形如数组名=(值1 值2 ... 值n)shell数组下标从1开始。

  • ${数组名[下标]},读取指索引位置数组元素
  • 使用@*代替下标,获取数组中所有元素。
  • 使用{<span class="tag">#数组名</span>[@]}{<span class="tag">#数组名</span>[*]}获取数组元素个数。
arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]='new_value3'
echo $arr[3]
# new_value3
echo ${<span class="tag">#arr</span>[@]}
# 4
echo "arr[1]的长度为:${<span class="tag">#arr</span>[1]}" 
# arr[1]的长度为:6

6. 运算符

6.1. 赋值运算符

a=10
b=$a

6.2. 算术运算符

算数运算符支持+,-,*,/,%

6.2.1. expr表示法

echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200

使用expr表示方法时,表达式和运算符之间必须有空格。

6.2.2. $[]

echo $[10%3]
# 1

6.2.3. $(())

echo $((10*20))
# 200

6.3. 关系运算符

最常见的关系运算符是:==,!=,<,>,>=,<=

echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10>=10]
# 1

如下关系运算符只能使用在条件表达式if、while下,类似flag=[ $a -eq $b ]的直接赋值语句是非法的。关系运算符的条件表达式要放在一对方括号中,并且中间需要有空格。也可以使用(())替代[],此时-eq,-lt,-le之类的需要使用==,<,<=等替换。

[]搭配-eq -ne等使用,(())搭配|| &&等使用。

运算符 说明 举例
-eq 检测两个数是否相等,相等返回true。 [ $a -eq $b ]
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ]
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ]
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ]
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ]
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ]
if [ 1 -eq 1 ];then echo 'hello';fi;
# hello
if ((10>=10));then echo 'hello';fi;
# hello

6.4. 布尔、逻辑运算符

布尔、逻辑运算的条件表达式也要放在一对方括号中[]

运算符 说明 举例
! 非运算,表达式为true则返回false,否则返回true。 [ ! 10 -eq 0 ]
-o 或运算,有一个表达式为true则返回true。 [ 10 -lt 20 -o 10 -gt 100 ]
-a 与运算,两个表达式都为true才返回true。 [ 10 -lt 20 -a 10 -gt 100 ]
if [ ! 10 -eq 0 ];then echo 'hello';fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo 'hello';fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo 'hello';fi
# hello

-o也可以使用||替代,-a也可以使用&&替代,此时需要使用(())[[]]替代[]

if <a href="1010-55.html" class="internal-link"> 10==10 && 5==5 </a>;then echo 'hello';fi
# hello
if ((10==10 && 5==5));then echo 'hello';fi
# hello

7. 传递参数

在执行 Shell脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn代表一个数字,1为执行脚本的第一个参数,2为执行脚本的第二个参数,$0为执行的文件名。在为shell脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数,以$1 $2 … $n的形式输出所有参数。
$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ $*相同,但是使用时加引号,并在引号中返回每个参数,以$1 $2 … $n的形式输出所有参数。
$- 显示Shell使用的当前选项,与set功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

编写shell脚本如下:

set -e
echo "执行的文件名:$0"
echo "参数个数为$#"
echo "第一个参数为:$1"
echo "第二个参数为:$2"
echo "所有参数为:$@"
echo "进程ID号为:<article>
    <header>
        <h1>shell编程</h1>
        <time datetime="2023-01-24T00:00:00.000Z">2023年1月24日</time>
        <div class="tags">
            
            <span class="tag">linux</span>
            
        </div>
    </header>
    <section class="content">
        <p>本文主要介绍shell编程的基本语法以及实际应用中的常见命令。</p>
<h1>1. 注释</h1>
<h2>1.1. 单行注释</h2>
<pre><code class="language-shell"># 这是单行注释
</code></pre>
<h2>1.2. 多行注释</h2>
<pre><code class="language-shell">:&lt;&lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
</code></pre>
<p>多行注释<code>EOF</code>也可替换成<code>!</code>或<code>&#39;</code></p>
<pre><code class="language-shell">:&lt;&lt;&#39;
多行注释内容
多行注释内容
多行注释内容
&#39;

:&lt;&lt;!
多行注释内容
多行注释内容
多行注释内容
!
</code></pre>
<h1>2. 变量</h1>
<h2>2.1. 变量定义</h2>
<p>使用<code>VARIABLENAME=VALUE</code>的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。</p>
<h2>2.2. 变量使用</h2>
<p>只需要在变量前加<code>$</code>符号,变量加<code>{}</code>是可选的,方便解释器识别边界。将变量加上<code>{}</code>是一个好习惯,不容易出错。</p>
<pre><code class="language-shell">your_age=25
your_name=&quot;shinerio&quot;
your_name=shinerio
your_name=&#39;shinerio&#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &quot;${your_name}hello&quot; &lt;span class=&quot;tag&quot;&gt;#这里&lt;/span&gt;{}必须添加,否则解释器认为是${your_namehello}
str=&#39;hello&#39;&#39; # 非法
str=&#39;hello&#39;__&#39;world&#39; # 成对出现的单引号做字符拼接
echo $str &lt;span class=&quot;tag&quot;&gt;#输出hello__world&lt;/span&gt;
str1=&#39;helloworld${your_age}\nnew line&#39;
str2=&quot;helloworld${your_age}\nnew line&quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&lt;span class=&quot;tag&quot;&gt;#helloworld25&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;#new&lt;/span&gt; line
</code></pre>
<h2>2.3. 只读变量</h2>
<p>使用<code>readonly VARIABLENAME</code>设置变量只读,只读变量的值不能更改</p>
<pre><code class="language-shell">readonly name=&#39;jack&#39;
name=&#39;kelly&#39;
zsh: read-only variable: name
</code></pre>
<h2>2.4. 删除变量</h2>
<p>使用<code>unset VARIABLENAME</code>删除变量。</p>
<h1>3. 字符串操作</h1>
<h2>3.1. 字符串拼接</h2>
<pre><code class="language-shell">str1=&quot;hello&quot;${your_name}&quot;world&quot;
str2=&quot;hello${your_name}world&quot;
str3=&#39;hello&#39;${your_name}&#39;world&#39;
</code></pre>
<h2>3.2. 字符串长度</h2>
<pre><code class="language-shell">str=&#39;hello&#39;
echo ${&lt;span class=&quot;tag&quot;&gt;#str&lt;/span&gt;}
5
</code></pre>
<h2>3.3. 字符串截取</h2>
<p><code>${string:start:length}</code>,索引从0开始,从start(包含)开始截取共计length长度的字符。</p>
<pre><code class="language-shell">str=&#39;helloworld&#39;
echo ${str:0:5}
hello
</code></pre>
<h2>3.4. 字符串运算符</h2>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>检测两个字符串是否相等,相等返回true</td>
<td><code>[ &#39;hello&#39; = &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>检测两个字符串是否相等,不相等返回true</td>
<td><code>[ &#39;hello&#39; != &#39;ello&#39; ]</code></td>
</tr>
<tr>
<td><code>-z</code></td>
<td>检测字符串长度是否为0,为0返回true</td>
<td><code>[ -z &#39;&#39; ]</code></td>
</tr>
<tr>
<td><code>-n </code></td>
<td>检测字符串长度是否不为0,不为0返回true</td>
<td><code>[ -n &#39;hello&#39; ]</code></td>
</tr>
<tr>
<td><code>$</code></td>
<td>检测字符串是否为空,不为空返回true</td>
<td><code>[ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ &#39;hello&#39; = &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &#39;hello&#39; != &#39;ello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -z &#39;&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ -n &#39;hello&#39; ];then echo &#39;hello&#39;;fi
# hello
if [ &lt;p&gt;本文主要介绍shell编程的基本语法以及实际应用中的常见命令。&lt;/p&gt;
&lt;h1&gt;1. 注释&lt;/h1&gt;
&lt;h2&gt;1.1. 单行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 这是单行注释
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.2. 多行注释&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;EOF
多行注释内容
多行注释内容
多行注释内容
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多行注释&lt;code&gt;EOF&lt;/code&gt;也可替换成&lt;code&gt;!&lt;/code&gt;或&lt;code&gt;&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;:&amp;lt;&amp;lt;&amp;#39;
多行注释内容
多行注释内容
多行注释内容
&amp;#39;

:&amp;lt;&amp;lt;!
多行注释内容
多行注释内容
多行注释内容
!
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;2. 变量&lt;/h1&gt;
&lt;h2&gt;2.1. 变量定义&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;VARIABLENAME=VALUE&lt;/code&gt;的形式,VALUE如果是字符串的话,可以使用单引号、双引号或者不加引号。单引号内的任何字符都会原样输出,不能进行转义,单引号内不能单独出现一个单引号,但可成对出现,作为字符串拼接使用。双引号内可以有变量,可以出现转义字符。&lt;/p&gt;
&lt;h2&gt;2.2. 变量使用&lt;/h2&gt;
&lt;p&gt;只需要在变量前加&lt;code&gt;$&lt;/code&gt;符号,变量加&lt;code&gt;{}&lt;/code&gt;是可选的,方便解释器识别边界。将变量加上&lt;code&gt;{}&lt;/code&gt;是一个好习惯,不容易出错。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;your_age=25
your_name=&amp;quot;shinerio&amp;quot;
your_name=shinerio
your_name=&amp;#39;shinerio&amp;#39;
echo $your_age # 输出25
echo $your_name # 输出shinerio
echo &amp;quot;${your_name}hello&amp;quot; &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#这里&amp;lt;/span&amp;gt;{}必须添加,否则解释器认为是${your_namehello}
str=&amp;#39;hello&amp;#39;&amp;#39; # 非法
str=&amp;#39;hello&amp;#39;__&amp;#39;world&amp;#39; # 成对出现的单引号做字符拼接
echo $str &amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#输出hello__world&amp;lt;/span&amp;gt;
str1=&amp;#39;helloworld${your_age}\nnew line&amp;#39;
str2=&amp;quot;helloworld${your_age}\nnew line&amp;quot;
echo $str1 # 输出helloworld${your_age}\nnew line
echo $str2 # 输出helloworld25\nnew line
echo -e $str2 # -e开启转义 \n表示换行 echo默认换行,通过\c强制不换行
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#helloworld25&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#new&amp;lt;/span&amp;gt; line
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.3. 只读变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;readonly VARIABLENAME&lt;/code&gt;设置变量只读,只读变量的值不能更改&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;readonly name=&amp;#39;jack&amp;#39;
name=&amp;#39;kelly&amp;#39;
zsh: read-only variable: name
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.4. 删除变量&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;unset VARIABLENAME&lt;/code&gt;删除变量。&lt;/p&gt;
&lt;h1&gt;3. 字符串操作&lt;/h1&gt;
&lt;h2&gt;3.1. 字符串拼接&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str1=&amp;quot;hello&amp;quot;${your_name}&amp;quot;world&amp;quot;
str2=&amp;quot;hello${your_name}world&amp;quot;
str3=&amp;#39;hello&amp;#39;${your_name}&amp;#39;world&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2. 字符串长度&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;hello&amp;#39;
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#str&amp;lt;/span&amp;gt;}
5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3. 字符串截取&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;${string:start:length}&lt;/code&gt;,索引从0开始,从start(包含)开始截取共计length长度的字符。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;str=&amp;#39;helloworld&amp;#39;
echo ${str:0:5}
hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.4. 字符串运算符&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个字符串是否相等,不相等返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否为0,为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -z &amp;#39;&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n &lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串长度是否不为0,不为0返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ -n &amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测字符串是否为空,不为空返回true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $&amp;#39;hello&amp;#39; ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ &amp;#39;hello&amp;#39; = &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ &amp;#39;hello&amp;#39; != &amp;#39;ello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -z &amp;#39;&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ -n &amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ $&amp;#39;hello&amp;#39; ];then echo &amp;#39;hello&amp;#39;;fi
str=&amp;#39;hello&amp;#39;
if [ $str ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意字符串的等值判断是一个等号&lt;code&gt;&amp;quot;=&amp;quot;&lt;/code&gt;,与下文要讲的逻辑运算符使用两个等号&lt;code&gt;&amp;quot;==&amp;quot;&lt;/code&gt;做等值判断不一样。&lt;/p&gt;
&lt;h1&gt;4. 文件测试运算符&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-b file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是块设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-c file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是字符设备文件,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是目录,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-g file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SGID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-k file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否是有名管道,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否设置了&lt;code&gt;SUID&lt;/code&gt;位,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-r file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可读,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可写,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-x file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否可执行,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件是否为空(文件大小是否大于0),不为空返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测文件(包括目录)是否存在,如果是,则返回true。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;f-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -f &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# file
if &amp;lt;a href=&amp;quot;d-home.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -d &amp;#39;/home&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;directory&amp;#39;;else echo &amp;#39;file&amp;#39;;fi
# directory
if &amp;lt;a href=&amp;quot;e-tmpfake-file.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; -e &amp;#39;/tmp/fake_file&amp;#39; &amp;lt;/a&amp;gt;;then echo &amp;#39;exist&amp;#39;;else echo &amp;#39;not exist&amp;#39;;fi
# not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;5. 数组&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;shell&lt;/code&gt;只支持一维数组,用括号表示,元素通过空格分隔,形如&lt;code&gt;数组名=(值1 值2 ... 值n)&lt;/code&gt;。&lt;code&gt;shell&lt;/code&gt;数组下标从&lt;code&gt;1&lt;/code&gt;开始。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${数组名[下标]}&lt;/code&gt;,读取指索引位置数组元素&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;@&lt;/code&gt;或&lt;code&gt;*&lt;/code&gt;代替下标,获取数组中所有元素。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[@]}&lt;/code&gt;或&lt;code&gt;{&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#数组名&amp;lt;/span&amp;gt;[*]}&lt;/code&gt;获取数组元素个数。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&amp;#39;new_value3&amp;#39;
echo $arr[3]
# new_value3
echo ${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[@]}
# 4
echo &amp;quot;arr[1]的长度为:${&amp;lt;span class=&amp;quot;tag&amp;quot;&amp;gt;#arr&amp;lt;/span&amp;gt;[1]}&amp;quot; 
# arr[1]的长度为:6
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;6. 运算符&lt;/h1&gt;
&lt;h2&gt;6.1. 赋值运算符&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;a=10
b=$a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.2. 算术运算符&lt;/h2&gt;
&lt;p&gt;算数运算符支持&lt;code&gt;+,-,*,/,%&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;6.2.1. expr表示法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;使用expr表示方法时,表达式和运算符之间必须有空格。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2.2. &lt;code&gt;$[]&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10%3]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2.3. &lt;code&gt;$(())&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $((10*20))
# 200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.3. 关系运算符&lt;/h2&gt;
&lt;p&gt;最常见的关系运算符是:&lt;code&gt;==,!=,&amp;lt;,&amp;gt;,&amp;gt;=,&amp;lt;=&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&amp;gt;=10]
# 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下关系运算符只能使用在条件表达式&lt;code&gt;if、while&lt;/code&gt;下,类似&lt;code&gt;flag=[ $a -eq $b ]&lt;/code&gt;的直接赋值语句是非法的。关系运算符的条件表达式要放在&lt;strong&gt;一对&lt;/strong&gt;方括号中,并且中间需要有空格。也可以使用&lt;code&gt;(())&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;,此时&lt;code&gt;-eq,-lt,-le&lt;/code&gt;之类的需要使用&lt;code&gt;==,&amp;lt;,&amp;lt;=&lt;/code&gt;等替换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[]&lt;/code&gt;搭配&lt;code&gt;-eq -ne&lt;/code&gt;等使用,&lt;code&gt;(())&lt;/code&gt;搭配&lt;code&gt;|| &amp;amp;&amp;amp;&lt;/code&gt;等使用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否相等,相等返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -eq $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测两个数是否不相等,不相等返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ne $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -gt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -lt $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否大于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -ge $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检测左边的数是否小于等于右边的,如果是,则返回 true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ $a -le $b ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ 1 -eq 1 ];then echo &amp;#39;hello&amp;#39;;fi;
# hello
if ((10&amp;gt;=10));then echo &amp;#39;hello&amp;#39;;fi;
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6.4. 布尔、逻辑运算符&lt;/h2&gt;
&lt;p&gt;布尔、逻辑运算的条件表达式也要放在一对方括号中&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;运算符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非运算,表达式为true则返回false,否则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ! 10 -eq 0 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或运算,有一个表达式为true则返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -o 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与运算,两个表达式都为true才返回true。&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ 10 -lt 20 -a 10 -gt 100 ]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if [ ! 10 -eq 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;code&gt;-o&lt;/code&gt;也可以使用&lt;code&gt;||&lt;/code&gt;替代,&lt;code&gt;-a&lt;/code&gt;也可以使用&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;替代,此时需要使用&lt;code&gt;(())&lt;/code&gt;或&lt;code&gt;[[]]&lt;/code&gt;替代&lt;code&gt;[]&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if &amp;lt;a href=&amp;quot;1010-55.html&amp;quot; class=&amp;quot;internal-link&amp;quot;&amp;gt; 10==10 &amp;amp;&amp;amp; 5==5 &amp;lt;/a&amp;gt;;then echo &amp;#39;hello&amp;#39;;fi
# hello
if ((10==10 &amp;amp;&amp;amp; 5==5));then echo &amp;#39;hello&amp;#39;;fi
# hello
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;7. 传递参数&lt;/h1&gt;
&lt;p&gt;在执行 &lt;code&gt;Shell&lt;/code&gt;脚本时,向脚本传递参数,脚本内获取参数的格式为:&lt;code&gt;$n&lt;/code&gt;。&lt;code&gt;n&lt;/code&gt;代表一个数字,&lt;code&gt;1&lt;/code&gt;为执行脚本的第一个参数,&lt;code&gt;2&lt;/code&gt;为执行脚本的第二个参数,&lt;code&gt;$0&lt;/code&gt;为执行的文件名。在为&lt;code&gt;shell&lt;/code&gt;脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数处理&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;传递到脚本的参数个数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以一个单字符串显示所有向脚本传递的参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;脚本运行的当前进程ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;后台运行的最后一个进程的ID号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与&lt;code&gt;$*&lt;/code&gt;相同,但是使用时加引号,并在引号中返回每个参数,以&lt;code&gt;$1 $2 … $n&lt;/code&gt;的形式输出所有参数。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示Shell使用的当前选项,与set功能相同。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set -e
echo &amp;quot;执行的文件名:$0&amp;quot;
echo &amp;quot;参数个数为$#&amp;quot;
echo &amp;quot;第一个参数为:$1&amp;quot;
echo &amp;quot;第二个参数为:$2&amp;quot;
echo &amp;quot;所有参数为:$@&amp;quot;
echo &amp;quot;进程ID号为:$$&amp;quot;
echo &amp;quot;当前shell选项为$-&amp;quot;
echo &amp;quot;上一个命令退出的状态为$?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行结果如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;$ sh test.sh param1 &amp;quot;param2 with space&amp;quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;8. 函数&lt;/h1&gt;
&lt;p&gt;函数定义通过&lt;code&gt;function_name(){}&lt;/code&gt;的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。&lt;/p&gt;
&lt;p&gt;编写&lt;code&gt;shell&lt;/code&gt;脚本如下:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;sayhello(){
    echo &amp;quot;hello&amp;quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &amp;quot;hello, $1 $2 $3&amp;quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;br&gt;hello, zhangsan lisi wangwu&lt;br&gt;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;9. 命令替换&lt;/h1&gt;
&lt;p&gt;命令替换可以将一个命令的输出作为另外一个命令的参数。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;10. let命令&lt;/h1&gt;
&lt;p&gt;let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自加操作:&lt;code&gt;let no++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自减操作:&lt;code&gt;let no--&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;简写形式 &lt;code&gt;let no+=10&lt;/code&gt;,&lt;code&gt;let no-=20&lt;/code&gt;,分别等同于&lt;code&gt;let no=no+10&lt;/code&gt;,&lt;code&gt;let no=no-20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;11. 流程控制&lt;/h1&gt;
&lt;h2&gt;11.1. if&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;if ((10&amp;lt;2));then
    echo &amp;quot;10小于2&amp;quot;
elif ((10&amp;gt;20));then
    echo &amp;quot;a大于10&amp;quot;
else
    echo &amp;quot;10大于2且小于10&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2. case&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case&lt;/code&gt;每一种情况以右括号结尾,执行到&lt;code&gt;;;&lt;/code&gt;结束&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;case 10 in
0|1)
    echo &amp;quot;a为0或1&amp;quot; 
    ;;
11|12) 
    echo &amp;quot;a为11或12&amp;quot;
    ;;
*) 
# *用来匹配所有情况
    echo &amp;quot;a为10&amp;quot; 
    ;;
esac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3. while&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
while(($count&amp;lt;5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.4. util&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;count=0
until(($count&amp;gt;=5))
do
    echo $count
    let count++
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.5. for&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# for写法1
for ((count=0;$count&amp;lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.6. break和continue&lt;/h2&gt;
&lt;p&gt;用法与一般编程语言类似,break跳出循环,continue跳出当前循环&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;for ((count=0;$count&amp;gt;=0;count=$count+1))
do
    if (($count&amp;gt;=5));then
        break;
    fi
    echo $count
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;12. 输入输出重定向&lt;/h1&gt;
&lt;h2&gt;12.1. 输出重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;gt; file&lt;/code&gt;将命令输出结果保存的file文件中。&lt;code&gt;&amp;gt;&lt;/code&gt;从文件头开始写,会覆盖旧内容,&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;将内容追加到文件末尾&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将who命令的输出保存的users文件中,可以通过cat users查看
who &amp;gt; users 
# 将字符串hello world保存到text.txt文件中
echo &amp;quot;hello world&amp;quot; &amp;gt; text.txt 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2. 输入重定向&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;command &amp;lt; file&lt;/code&gt;从file文件获取输入&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &amp;lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &amp;lt; infile &amp;gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &amp;lt; /etc/passwd &amp;gt; result
cat result 
# 123
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.3. 文件描述符&lt;/h2&gt;
&lt;p&gt;一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。&lt;/li&gt;
&lt;li&gt;标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。&lt;/li&gt;
&lt;li&gt;标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&amp;gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;amp;&amp;gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &amp;gt; result 2&amp;gt;&amp;amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&amp;gt;result 2&amp;gt;error_trace
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.4. Here Document&lt;/h2&gt;
&lt;p&gt;将两个&lt;code&gt;EOF&lt;/code&gt;之间的内容(document) 作为输入传递给&lt;code&gt;command&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# command &amp;lt;&amp;lt; EOF
# document
# EOF

cat &amp;lt;&amp;lt; EOF
hello
shinerio
learn shell
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;结尾的&lt;code&gt;EOF&lt;/code&gt;一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和&lt;code&gt;tab&lt;/code&gt;缩进。开始的&lt;code&gt;EOF&lt;/code&gt;前后的空格会被忽略掉。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;12.5. /dev/null&lt;/h2&gt;
&lt;p&gt;如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。&lt;code&gt;command &amp;gt; /dev/null&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;cat users &amp;gt; /dev/null
cat users &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;13. set命令&lt;/h1&gt;
&lt;p&gt;set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-e  若指令传回值不等于0,则立即退出shell。&lt;/li&gt;
&lt;li&gt;-f  取消使用通配符。&lt;/li&gt;
&lt;li&gt;-n  只读取指令,而不实际执行。&lt;/li&gt;
&lt;li&gt;-x  执行指令后,会先显示该指令及所下的参数。&lt;/li&gt;
&lt;/ul&gt;
#39;hello&#39; ];then echo &#39;hello&#39;;fi
str=&#39;hello&#39;
if [ $str ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p>注意字符串的等值判断是一个等号<code>&quot;=&quot;</code>,与下文要讲的逻辑运算符使用两个等号<code>&quot;==&quot;</code>做等值判断不一样。</p>
<h1>4. 文件测试运算符</h1>
<table>
<thead>
<tr>
<th>操作符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b file</code></td>
<td>检测文件是否是块设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-c file</code></td>
<td>检测文件是否是字符设备文件,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-d file</code></td>
<td>检测文件是否是目录,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-f file</code></td>
<td>检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-g file</code></td>
<td>检测文件是否设置了<code>SGID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-k file</code></td>
<td>检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true。</td>
</tr>
<tr>
<td><code>-p file</code></td>
<td>检测文件是否是有名管道,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-u file</code></td>
<td>检测文件是否设置了<code>SUID</code>位,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-r file</code></td>
<td>检测文件是否可读,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-w file</code></td>
<td>检测文件是否可写,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-x file</code></td>
<td>检测文件是否可执行,如果是,则返回true。</td>
</tr>
<tr>
<td><code>-s file</code></td>
<td>检测文件是否为空(文件大小是否大于0),不为空返回true。</td>
</tr>
<tr>
<td><code>-e file</code></td>
<td>检测文件(包括目录)是否存在,如果是,则返回true。</td>
</tr>
</tbody></table>
<pre><code class="language-shell">if &lt;a href=&quot;f-home.html&quot; class=&quot;internal-link&quot;&gt; -f &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# file
if &lt;a href=&quot;d-home.html&quot; class=&quot;internal-link&quot;&gt; -d &#39;/home&#39; &lt;/a&gt;;then echo &#39;directory&#39;;else echo &#39;file&#39;;fi
# directory
if &lt;a href=&quot;e-tmpfake-file.html&quot; class=&quot;internal-link&quot;&gt; -e &#39;/tmp/fake_file&#39; &lt;/a&gt;;then echo &#39;exist&#39;;else echo &#39;not exist&#39;;fi
# not exist
</code></pre>
<h1>5. 数组</h1>
<p><code>shell</code>只支持一维数组,用括号表示,元素通过空格分隔,形如<code>数组名=(值1 值2 ... 值n)</code>。<code>shell</code>数组下标从<code>1</code>开始。</p>
<ul>
<li><code>${数组名[下标]}</code>,读取指索引位置数组元素</li>
<li>使用<code>@</code>或<code>*</code>代替下标,获取数组中所有元素。</li>
<li>使用<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[@]}</code>或<code>{&lt;span class=&quot;tag&quot;&gt;#数组名&lt;/span&gt;[*]}</code>获取数组元素个数。</li>
</ul>
<pre><code class="language-shell">arr=(value1 value2 value3 value4)
echo ${arr[3]}
# value3
echo ${arr[*]} 
# value1 value2 value3 value4
echo ${arr[@]} 
# value1 value2 value3 value4
arr[3]=&#39;new_value3&#39;
echo $arr[3]
# new_value3
echo ${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[@]}
# 4
echo &quot;arr[1]的长度为:${&lt;span class=&quot;tag&quot;&gt;#arr&lt;/span&gt;[1]}&quot; 
# arr[1]的长度为:6
</code></pre>
<h1>6. 运算符</h1>
<h2>6.1. 赋值运算符</h2>
<pre><code class="language-shell">a=10
b=$a
</code></pre>
<h2>6.2. 算术运算符</h2>
<p>算数运算符支持<code>+,-,*,/,%</code></p>
<h3>6.2.1. expr表示法</h3>
<pre><code class="language-shell">echo `expr 10 + 20`
# 30
echo $(expr 20 / 2)
# 10
echo $(expr 10 \* 20)  # 使用expr进行乘法运算时必须使用\进行转义
# 200
</code></pre>
<blockquote>
<p>使用expr表示方法时,表达式和运算符之间必须有空格。</p>
</blockquote>
<h3>6.2.2. <code>$[]</code></h3>
<pre><code class="language-shell">echo $[10%3]
# 1
</code></pre>
<h3>6.2.3. <code>$(())</code></h3>
<pre><code class="language-shell">echo $((10*20))
# 200
</code></pre>
<h2>6.3. 关系运算符</h2>
<p>最常见的关系运算符是:<code>==,!=,&lt;,&gt;,&gt;=,&lt;=</code></p>
<pre><code class="language-shell">echo $[10==10]
# 1
flag=$[20==10]
echo $flag
# 1
echo $[10&gt;=10]
# 1
</code></pre>
<p>如下关系运算符只能使用在条件表达式<code>if、while</code>下,类似<code>flag=[ $a -eq $b ]</code>的直接赋值语句是非法的。关系运算符的条件表达式要放在<strong>一对</strong>方括号中,并且中间需要有空格。也可以使用<code>(())</code>替代<code>[]</code>,此时<code>-eq,-lt,-le</code>之类的需要使用<code>==,&lt;,&lt;=</code>等替换。</p>
<blockquote>
<p><code>[]</code>搭配<code>-eq -ne</code>等使用,<code>(())</code>搭配<code>|| &amp;&amp;</code>等使用。</p>
</blockquote>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>-eq</code></td>
<td>检测两个数是否相等,相等返回true。</td>
<td><code>[ $a -eq $b ]</code></td>
</tr>
<tr>
<td><code>-ne</code></td>
<td>检测两个数是否不相等,不相等返回 true。</td>
<td><code>[ $a -ne $b ]</code></td>
</tr>
<tr>
<td><code>-gt</code></td>
<td>检测左边的数是否大于右边的,如果是,则返回 true。</td>
<td><code>[ $a -gt $b ]</code></td>
</tr>
<tr>
<td><code>-lt</code></td>
<td>检测左边的数是否小于右边的,如果是,则返回 true。</td>
<td><code>[ $a -lt $b ]</code></td>
</tr>
<tr>
<td><code>-ge</code></td>
<td>检测左边的数是否大于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -ge $b ]</code></td>
</tr>
<tr>
<td><code>-le</code></td>
<td>检测左边的数是否小于等于右边的,如果是,则返回 true。</td>
<td><code>[ $a -le $b ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ 1 -eq 1 ];then echo &#39;hello&#39;;fi;
# hello
if ((10&gt;=10));then echo &#39;hello&#39;;fi;
# hello
</code></pre>
<h2>6.4. 布尔、逻辑运算符</h2>
<p>布尔、逻辑运算的条件表达式也要放在一对方括号中<code>[]</code>。</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>举例</th>
</tr>
</thead>
<tbody><tr>
<td><code>!</code></td>
<td>非运算,表达式为true则返回false,否则返回true。</td>
<td><code>[ ! 10 -eq 0 ]</code></td>
</tr>
<tr>
<td><code>-o</code></td>
<td>或运算,有一个表达式为true则返回true。</td>
<td><code>[ 10 -lt 20 -o 10 -gt 100 ]</code></td>
</tr>
<tr>
<td><code>-a</code></td>
<td>与运算,两个表达式都为true才返回true。</td>
<td><code>[ 10 -lt 20 -a 10 -gt 100 ]</code></td>
</tr>
</tbody></table>
<pre><code class="language-shell">if [ ! 10 -eq 0 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 10 -a 10 -ge 10 ];then echo &#39;hello&#39;;fi
# hello
if [ 10 -ge 20 -o 10 -ge 0 ];then echo &#39;hello&#39;;fi
# hello
</code></pre>
<p> <code>-o</code>也可以使用<code>||</code>替代,<code>-a</code>也可以使用<code>&amp;&amp;</code>替代,此时需要使用<code>(())</code>或<code>[[]]</code>替代<code>[]</code>。</p>
<pre><code class="language-shell">if &lt;a href=&quot;1010-55.html&quot; class=&quot;internal-link&quot;&gt; 10==10 &amp;&amp; 5==5 &lt;/a&gt;;then echo &#39;hello&#39;;fi
# hello
if ((10==10 &amp;&amp; 5==5));then echo &#39;hello&#39;;fi
# hello
</code></pre>
<h1>7. 传递参数</h1>
<p>在执行 <code>Shell</code>脚本时,向脚本传递参数,脚本内获取参数的格式为:<code>$n</code>。<code>n</code>代表一个数字,<code>1</code>为执行脚本的第一个参数,<code>2</code>为执行脚本的第二个参数,<code>$0</code>为执行的文件名。在为<code>shell</code>脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。另外,还有几个特殊字符用来处理参数:</p>
<table>
<thead>
<tr>
<th>参数处理</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$#</code></td>
<td>传递到脚本的参数个数</td>
</tr>
<tr>
<td><code>$*</code></td>
<td>以一个单字符串显示所有向脚本传递的参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$</code></td>
<td>脚本运行的当前进程ID号</td>
</tr>
<tr>
<td><code>$!</code></td>
<td>后台运行的最后一个进程的ID号</td>
</tr>
<tr>
<td><code>$@</code></td>
<td>与<code>$*</code>相同,但是使用时加引号,并在引号中返回每个参数,以<code>$1 $2 … $n</code>的形式输出所有参数。</td>
</tr>
<tr>
<td><code>$-</code></td>
<td>显示Shell使用的当前选项,与set功能相同。</td>
</tr>
<tr>
<td><code>$?</code></td>
<td>显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。</td>
</tr>
</tbody></table>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-bash">set -e
echo &quot;执行的文件名:$0&quot;
echo &quot;参数个数为$#&quot;
echo &quot;第一个参数为:$1&quot;
echo &quot;第二个参数为:$2&quot;
echo &quot;所有参数为:$@&quot;
echo &quot;进程ID号为:$&quot;
echo &quot;当前shell选项为$-&quot;
echo &quot;上一个命令退出的状态为$?&quot;
</code></pre>
<p>执行结果如下:</p>
<pre><code class="language-shell">$ sh test.sh param1 &quot;param2 with space&quot;
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0
</code></pre>
<h1>8. 函数</h1>
<p>函数定义通过<code>function_name(){}</code>的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。</p>
<p>编写<code>shell</code>脚本如下:</p>
<pre><code class="language-shell">sayhello(){
    echo &quot;hello&quot;
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo &quot;hello, $1 $2 $3&quot;
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?
</code></pre>
<p>输出如下:</p>
<blockquote>
<p>hello<br>hello, zhangsan lisi wangwu<br>1</p>
</blockquote>
<h1>9. 命令替换</h1>
<p>命令替换可以将一个命令的输出作为另外一个命令的参数。</p>
<pre><code class="language-shell"># command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录
</code></pre>
<h1>10. let命令</h1>
<p>let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。</p>
<ul>
<li>自加操作:<code>let no++</code></li>
<li>自减操作:<code>let no--</code></li>
<li>简写形式 <code>let no+=10</code>,<code>let no-=20</code>,分别等同于<code>let no=no+10</code>,<code>let no=no-20</code></li>
</ul>
<h1>11. 流程控制</h1>
<h2>11.1. if</h2>
<pre><code class="language-shell">if ((10&lt;2));then
    echo &quot;10小于2&quot;
elif ((10&gt;20));then
    echo &quot;a大于10&quot;
else
    echo &quot;10大于2且小于10&quot;
fi
</code></pre>
<h2>11.2. case</h2>
<p><code>case</code>每一种情况以右括号结尾,执行到<code>;;</code>结束</p>
<pre><code class="language-shell">case 10 in
0|1)
    echo &quot;a为0或1&quot; 
    ;;
11|12) 
    echo &quot;a为11或12&quot;
    ;;
*) 
# *用来匹配所有情况
    echo &quot;a为10&quot; 
    ;;
esac
</code></pre>
<h2>11.3. while</h2>
<pre><code class="language-shell">count=0
while(($count&lt;5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.4. util</h2>
<pre><code class="language-shell">count=0
until(($count&gt;=5))
do
    echo $count
    let count++
done
</code></pre>
<h2>11.5. for</h2>
<pre><code class="language-shell"># for写法1
for ((count=0;$count&lt;5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done
</code></pre>
<h2>11.6. break和continue</h2>
<p>用法与一般编程语言类似,break跳出循环,continue跳出当前循环</p>
<pre><code class="language-shell">for ((count=0;$count&gt;=0;count=$count+1))
do
    if (($count&gt;=5));then
        break;
    fi
    echo $count
done
</code></pre>
<h1>12. 输入输出重定向</h1>
<h2>12.1. 输出重定向</h2>
<p><code>command &gt; file</code>将命令输出结果保存的file文件中。<code>&gt;</code>从文件头开始写,会覆盖旧内容,<code>&gt;&gt;</code>将内容追加到文件末尾</p>
<pre><code class="language-shell"># 将who命令的输出保存的users文件中,可以通过cat users查看
who &gt; users 
# 将字符串hello world保存到text.txt文件中
echo &quot;hello world&quot; &gt; text.txt 
</code></pre>
<h2>12.2. 输入重定向</h2>
<p><code>command &lt; file</code>从file文件获取输入</p>
<pre><code class="language-shell">wc -l /etc/passwd 
# 123 /etc/passwd
wc -l &lt; users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command &lt; infile &gt; outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l &lt; /etc/passwd &gt; result
cat result 
# 123
</code></pre>
<h2>12.3. 文件描述符</h2>
<p>一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件</p>
<ul>
<li>标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。</li>
<li>标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。</li>
<li>标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。</li>
</ul>
<pre><code class="language-shell"># 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2&gt;error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &amp;&gt;result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file &gt; result 2&gt;&amp;1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1&gt;result 2&gt;error_trace
</code></pre>
<h2>12.4. Here Document</h2>
<p>将两个<code>EOF</code>之间的内容(document) 作为输入传递给<code>command</code></p>
<pre><code class="language-bash"># command &lt;&lt; EOF
# document
# EOF

cat &lt;&lt; EOF
hello
shinerio
learn shell
EOF
</code></pre>
<blockquote>
<p>结尾的<code>EOF</code>一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和<code>tab</code>缩进。开始的<code>EOF</code>前后的空格会被忽略掉。</p>
</blockquote>
<h2>12.5. /dev/null</h2>
<p>如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。<code>command &gt; /dev/null</code></p>
<pre><code class="language-shell">cat users &gt; /dev/null
cat users &gt; /dev/null 2&gt;&amp;1
</code></pre>
<h1>13. set命令</h1>
<p>set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:</p>
<ul>
<li>-e  若指令传回值不等于0,则立即退出shell。</li>
<li>-f  取消使用通配符。</li>
<li>-n  只读取指令,而不实际执行。</li>
<li>-x  执行指令后,会先显示该指令及所下的参数。</li>
</ul>

    </section>
</article>quot;
echo "当前shell选项为$-"
echo "上一个命令退出的状态为$?"

执行结果如下:

$ sh test.sh param1 "param2 with space"
执行的文件名:test.sh
参数个数为2
第一个参数为:param1
第二个参数为:param2 with space
所有参数为:param1 param2 with space
进程ID号为:3700
当前shell选项为ehB
上一个命令退出的状态为0

8. 函数

函数定义通过function_name(){}的形式定义,函数返回值可以显示用return返回,如果不加,将以最后一条命令的运行结果作为返回值,函数返回值只能是数字。函数也可以传递参数,但是函数定义的()中不需要申明。

编写shell脚本如下:

sayhello(){
    echo "hello"
}

# 注意函数调用只需要函数名,不需要加()
sayhello

sayhellowithparam(){
    echo "hello, $1 $2 $3"
    return 1
}

sayhellowithparam zhangsan lisi wangwu
echo $?

输出如下:

hello
hello, zhangsan lisi wangwu
1

9. 命令替换

命令替换可以将一个命令的输出作为另外一个命令的参数。

# command1 `command2`
cd `pwd` # 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下
cd `echo $HOME` # 将echo的输出作为cd的参数,即打开用户根目录

10. let命令

let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。

  • 自加操作:let no++
  • 自减操作:let no--
  • 简写形式 let no+=10let no-=20,分别等同于let no=no+10let no=no-20

11. 流程控制

11.1. if

if ((10<2));then
    echo "10小于2"
elif ((10>20));then
    echo "a大于10"
else
    echo "10大于2且小于10"
fi

11.2. case

case每一种情况以右括号结尾,执行到;;结束

case 10 in
0|1)
    echo "a为0或1" 
    ;;
11|12) 
    echo "a为11或12"
    ;;
*) 
# *用来匹配所有情况
    echo "a为10" 
    ;;
esac

11.3. while

count=0
while(($count<5))
do
    echo $count
    let count++
done

11.4. util

count=0
until(($count>=5))
do
    echo $count
    let count++
done

11.5. for

# for写法1
for ((count=0;$count<5;count=$count+1))
do
    echo $count
done

# for写法2
arr=(0 1 2 3 4)
for count in ${arr[*]}
do
    echo $int
done

# for写法3
for int in 0 1 2 3 4
do
    echo $int
done

11.6. break和continue

用法与一般编程语言类似,break跳出循环,continue跳出当前循环

for ((count=0;$count>=0;count=$count+1))
do
    if (($count>=5));then
        break;
    fi
    echo $count
done

12. 输入输出重定向

12.1. 输出重定向

command > file将命令输出结果保存的file文件中。>从文件头开始写,会覆盖旧内容,>>将内容追加到文件末尾

# 将who命令的输出保存的users文件中,可以通过cat users查看
who > users 
# 将字符串hello world保存到text.txt文件中
echo "hello world" > text.txt 

12.2. 输入重定向

command < file从file文件获取输入

wc -l /etc/passwd 
# 123 /etc/passwd
wc -l < users
# 123
# 第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容

# command < infile > outfile, 同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
wc -l < /etc/passwd > result
cat result 
# 123

12.3. 文件描述符

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
# 将标准错误输出重定向到error_trace
cat /tmp/fake_file 2>error_trace
cat error_trace
# cat: /tmp/fake_fule: No such file or directory

# 将标准输出和标准错误输出都重定向到result
cat /tmp/fake_file &>result
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准错误重定向到标准输出
ls /tmp/fake_file > result 2>&1
cat result
# cat: /tmp/fake_fule: No such file or directory

# 将标准输入重定向到result,将标准错误输出重定向到error_trace
cat /tmp/fake_file 1>result 2>error_trace

12.4. Here Document

将两个EOF之间的内容(document) 作为输入传递给command

# command << EOF
# document
# EOF

cat << EOF
hello
shinerio
learn shell
EOF

结尾的EOF一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和tab缩进。开始的EOF前后的空格会被忽略掉。

12.5. /dev/null

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。command > /dev/null

cat users > /dev/null
cat users > /dev/null 2>&1

13. set命令

set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。以下只列出常用的选项参数:

  • -e  若指令传回值不等于0,则立即退出shell。
  • -f  取消使用通配符。
  • -n  只读取指令,而不实际执行。
  • -x  执行指令后,会先显示该指令及所下的参数。