任何编程语言,常用的语法和代码结构其实不多的,如果为了快速的掌握入手一门编程语言,我认为只需要把该语言的常见语法和代码记下来,再结合实际需求去拼接成新的代码。这篇文章主要是记录bash shell的一些基本命令,便于日后复习。
shell不是具体哪一款程序,它是一类程序的统称,这些程序只要能够按照用户的要求去调用操作系统的接口,就可以称之为shell程序。常用shell程序有:bash, csh, tcsh, zsh等。
当我们在linux内打开一个terminal,此时就开启了一个shell程序供我们与操作系统进行交互。可以设置具体是开启了哪一款shell程序。
在terminal内执行:cat /etc/shells,结果如下:
>>cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/ksh
/bin/rksh
/bin/tcsh
/bin/csh
linux系统中当前安装的所有shell的列表存储在系统的/etc文件夹的"shells"文件中。默认情况下它具有只读权限,并且每当我们在系统中安装新shell时都会自动修改它。
在terminal内执行:echo $SHELL,结果如下图:
>>echo $SHELL
/bin/tcsh
在terminal内执行:man bash
变量名不需要声明,直接这样写:variable_name=variable_value。使用变量需要用$放在variable_name前就行,比如:
var="define variable"
echo $var
<< COMMENT
和COMMENT
之间加上注释# echo $var
<< comment
export var
test comment
echo "somethin"
comment
Bash脚本文件的第一行必须是:#!/bin/bash。#!
称为shebang,该行的其余部分是解释器的路径,用于指定bash shell在操作系统中的位置。
She Bang(#!
)是一个字符序列,由脚本开头的符号(#)和感叹号(!
)组成。在类似Unix的操作系统下,当带有shebang的脚本作为程序运行时,程序加载器会将第一行的其余行解析为解释器指令。因此,SheBang表示执行脚本行的解释器,并且它被称为执行各种脚本(如Bash,Python等)的路径指令。
shebang的格式很重要,格式不正确会导致命令工作不正常。因此,在创建脚本时,要始终记住SheBang格式的这两点:
#!
和解释器的路径之间,#
之前不应有任何空格。Bash使用空格来确定单独的项目,引号可用于处理带有空格字符的文本。引号分为单引号和双引号。使用简单的文本和字符串时,使用单引号和双引号没任何区别。但如果需要对shell变量扩展,则只能使用双引号。如果在单引号中使用变量,则不会将其视为变量。例子如下:
# Bash script:
var="define variable"
echo "The value is $var"
echo 'The value is $var'
# The result is:
The value is define variable
The value is $var
变量名可以包含字母、数字和下划线,并且其名称只能以字母和下划线开头。不能定义以任何数字开头的变量。Bash变量不必在变量声明时定义变量的数据类型。Bash变量是无类型的,只需通过分配其值来键入变量名称,它会自动判断数据类型。如果将数字值分配给变量,它将自动转为整数工作,如果将字符值分配给该变量,则它将转为字符串类型。
x
和X
视为两个不同的变量;例子如下:
# The bash script:
var="define variable"
echo "The value is $var"
var=123456
echo "The value is $var"
var=variable
echo "The value is $var"
# The result is:
The value is define variable
The value is 123456
The value is variable
数组可以定义为相似类型元素的集合。与大多数编程语言不同,bash脚本中的数组不必是相似类型元素的集合。由于Bash不能将字符串与数字区分开,因此数组可以同时包含字符串和数字。Bash不支持多维数组,Bash支持一维数字索引数组以及关联数组。要从最后一个访问数字索引数组,可以使用负索引。索引-1
是最后一个元素的参考。可以在数组中使用几个元素。
数字索引数组:
可以使用任何变量作为数字索引的数组,而无需声明它。创建索引数组的一般方法可以按以下形式定义:
ARRAY_NAME[index_1]=value_1
ARRAY_NAME[index_2]=value_2
ARRAY_NAME[index_n]=value_n
# 其中关键字index用于定义正整数
当然,也可以使用关键字declare
将变量显式声明为Bash数组,并且语法可以定义为:
declare -a ARRAY_NAME
# 其中,ARRAY_NAME表示分配给数组的名称
关联数组:
与数字索引数组不同,关联数组需要首先声明。可以使用关键字declare
和-A
(大写)选项来声明关联数组。语法定义为:
declare -A ARRAY_NAME
# 创建关联数组的通用方法可以按以下形式定义:
declare -A ARRAY_NAME
ARRAY_NAME[index_foo]=value_foo
ARRAY_NAME[index_bar]=value_bar
ARRAY_NAME[index_xyz]=value_xyz
# 其中index_用于定义任何字符串。
# 还可以通过以下方式编写以上形式:
declare -A ARRAY_NAME
ARRAY_NAME=(
[index_foo]=value_foo
[index_bar]=value_bar
[index_xyz]=value_xyz
)
数组初始化:
要初始化Bash数组,可以使用赋值运算符(=
),方法是指定括号内的元素列表,并用空格分隔,如下所示:
ARRAY_NAME=(element_1st element_2nd element_Nth)
注意:此处,第一个元素的索引为0。此外,赋值运算符(=)周围不应有空格。
数组引用:
${ARRAY_NAME[index]} # 要引用单个元素,需要知道元素的索引号
# 如果在索引位置使用@或*,它将扩展到数组
# 的所有成员
${!ARRAY_NAME[index]} # 检索和打印在索引或关联数组中使用的键(而不是它们各自的值)
${#ARRAY_NAME[@]} # 计算数组中包含的元素数
for i in "${!ARRAY_NAME[@]}" # 遍历数组中每个项目(元素)
ARRAY_NAME[index_n]="New Element" # 指定元素的索引或关联键将元素添加到索引或关联数组
unset ARRAY_NAME[index] # unset命令删除元素
SLICED_ARRAY=("${ARRAY_NAME[@]:m:n}") # 从给定的起始索引切到结束索引。要将数
# 组从起始索引m切到结束索引n
Shell或UNIX系统中都有两种类型的变量:系统定义的变量和用户定义的变量。
系统定义的变量是由操作系统本身创建和维护的预定义变量,通常是以大写字母进行定义的。要了解系统中有哪些系统变量的列表,在命令行或脚本中输入命令:set,或env,或printenv。例子如下:
# The bash script:
echo $BASH
echo $BASH_VERSION
echo $OSTYPE
# The result is:
/bin/bash
4.2.46(2)-release
linux
用户定义的变量是由用户创建和维护,通常这些变量以小写形式定义,但不强制,也可以定义成大写的。第8点已经讲过如何定义变量了,这里不说了。
使用命令行参数可以给Bash脚本传递参数使脚本更具灵活性。在脚本运行时,以空格为间隔,跟在脚本名称后面。在Bash中,以下特殊变量会记录传递的参数:
$0
- 指定要调用的脚本的名称;$1
-$9
- 存储前9个自变量的名称,或可用作自变量的位置;$#
- 指定传递给脚本的参数总数(计数);$*
- 通过将所有命令行参数连接在一起来存储它们;$@
- 将参数列表存储为数组;$?
- 指定当前脚本的进程ID;$$
- 指定最后一个命令或最近执行过程的退出状态;$!
- 显示最后一个后台作业的ID;例子如下:
# The script is:
echo 'echo $0 is' $0
echo 'echo $1 is' $1
echo 'echo $2 is' $2
echo 'echo $3 is' $3
echo 'echo $4 is' $4
echo 'echo $5 is' $5
echo 'echo $6 is' $6
echo 'echo $# is' $#
echo 'echo $* is' $*
echo 'echo $@ is' $@
echo 'echo $? is' $?
echo 'echo $$ is' $$
echo 'echo $! is' $!
Run script: >>./test_bash.sh this is the first script
# The result is:
echo $0 is ./test_bash.sh
echo $1 is this
echo $2 is is
echo $3 is the
echo $4 is first
echo $5 is script
echo $6 is
echo $# is 5
echo $* is this is the first script
echo $@ is this is the first script
echo $? is 0
echo $$ is 621356
echo $! is
在$@数组里的参数可以传递给其它数组并引用。
args=("$@")
echo ${args[0]} ${args[1]} ${args[2]} ${args[3]}
# The result is:
this is the first
命令替换允许命令的输出替换命令本身。Bash通过在子shell环境中执行命令并用命令的标准输出替换命令,并删除任何尾随的换行符。常用的命令替换语法为:
# 语法1:将要替换的命令放在反引号里
variable_name=`command_name`
variable_name=`command_name [option...] argument1 argument2...`
# 语法2:将要替换的命令放在圆括号里,且以美元符号($)开头
variable_name=$(command_name)
variable_name=$(command_name [option...] argument1 argument2...)
要读取Bash用户输入,需要使用内置的Bash命令read
。它用于从用户处获取输入并分配给变量。它仅从Bash shell中读取一行。以下是read
命令的语法:
read # 可以读取单个或多个变量
read -p PROMPT # "Prompt": 显示提示信息(和用户输入同一行显示)
read -sp PROMPT # 将输入保持在静默模式,这样命令行上的用户输入都
# 将对其他用户隐藏。因此,通常使用命令行选项
# (-s,-p)来传递用户名并隐藏密码(静默模式)
read -a # -a指示脚本读取数组,而variable_name是引用的数组变量名称
例子如下:
# The script is:
read -p "enter two values: " a b
echo "The two values are : $a, $b"
read -a array
echo "The array is ${array[0]}, ${array[1]}"
# 执行结果
>>./bash_ex.sh
enter two values: first second
The two values are : first, second
arr1 arr2 arr3
The array is arr1, arr2
Bash Shell提供了不同的日期命令以及不同的格式选项。我们可以使用这些命令将Bash日期格式化为所需的日期。可以使用date
命令来显示或更改系统的当前日期和时间值。使用date
命令以不同的格式打印日期和时间值。我们还可以使用此命令来计算与日期和时间值相关的任务。如果不带任何选项使用date
命令,它将打印当前系统的日期和时间值。此命令包含多个格式化选项以格式化输出。
Bash sleep命令用于在指定的时间段内插入延迟或暂停执行。出于特定目的需要暂停执行任何命令时,可以将该命令与特定时间值一起使用。可以按秒(s),分钟(m),小时(h)和天(d)设置延迟量。Bash中sleep命令的语法为:
sleep number[suffix]
# 可以使用正整数或小数作为时间值。后缀是可选部分。可以将以下任意一项用作后缀:
# s - 表示秒;m - 表示分钟;h - 表示小时;d - 表示天
# 注意:如果没有后缀,则数字以秒为单位(默认情况下)。
# 如果指定了两个或多个参数,则总的时间将被视为等于值之和的时间。
例子如下:
# The script is:
date +"%H:%M:%S"
sleep 1m 10s
date +"%H:%M:%S"
sleep 9s
date +"%H:%M:%S"
# 输出结果为:
21:03:10
21:04:20
21:04:29
bash脚本中,可以对数值执行算术运算以获得所需的结果。Bash Shell支持11种算术运算符。
运算符 | 描述 | 例子 |
+ | 加法,数字(操作数)的加法 | $(( 5 + 3 )),结果为:8 |
- | 减法 | $(( 11 - 3 )),结果为:8 |
* | 乘法,操作数的乘法 | $(( 8 * 3 )),结果为:24 |
/ | 除法,第一个操作数除以第二个操作数并返回商 | $(( 14 / 3 )),结果为:4 |
** | 求幂,第一操作数的第二操作数的幂值 | $(( 10 ** 3 )),结果为:1000 |
% | 模,测量第一个操作数除以第二个操作数时的余数 | $(( 14 % 3 )),结果为:2 |
+= | 通过常量递增变量,用于按提供的常量递增第一个操作数的值 | x=5;let "x += 3";echo $x;结果为:8 |
-= | 通过常量递减变量,用于按提供的常量递减第一个操作数的值 | x=10;let "x -= 2";echo $x;结果为:8 |
*= | 将变量乘以常数,用于将第一个操作数的值乘以提供的常数 | x=10;let "x *= 3";echo $x;结果为:30 |
/= | 将变量除以常数,用于计算(变量/常数)的值并将结果存储回变量 | x=10;let "x /= 3";echo $x;结果为:3 |
%= | 变量除以常数的余数,用于计算(变量%常数)的值并将结果存储回变量 | x=10;let "x %= 3";echo $x;结果为:1 |
bash shell上有许多选项可以执行算术运算。下面提供了一些我们可以用来执行算术运算的选项:
# 双括号:双括号是在Bash shell中执行基本算术运算的最简单机制,可以使用带或不带前
# 导$的双括号来使用此方法。
# 语法: ((expression))
# Let构建:let是Bash的内置命令,它能够执行算术运算。
# 语法:let
# 反引号:使用反引号和expr(称为通用表达式求值器)执行算术扩展。
# 语法:`expr`
# 类似于let,但是不会将结果保存到变量中,它直接打印结果。与let不同,不需要将表达式
# 用引号引起来。需要在表达式的项目之间使用空格。注意,我们应该在命令替换中使用。
例子如下:
# The script is:
x=2
y=8
z=0
echo "[method1]The sum of $x and $y is:" $(($x + $y))
echo "[method1]The sum of 1 and 7 is:" $((1+7))
let "z = $((x+y))"
echo "[method2]The sum of $x and $y is: $z"
echo "[method3]The sum of $x and $y is: `expr $x + $y`"
输出结果:
[method1]The sum of 2 and 8 is: 10
[method1]The sum of 1 and 7 is: 8
[method2]The sum of 2 and 8 is: 10
[method3]The sum of 2 and 8 is: 10