版本记录
版本号 | 时间 |
---|---|
V1.0 | 2023.07.17 星期一 |
前言
Shell
脚本相信大家都用过,Shell 是一个用 C 语言编写的程序,它是用户使用Linux
的桥梁。Shell
既是一种命令语言,又是一种程序设计语言。Shell 脚本(shell script)
,是一种为 shell 编写的脚本程序。大家平时说的和用到的都是指的是shell脚本编程,不是指开发shell自身。这个模块我们就一起来看下shell脚本编程。感兴趣的可以看下面几篇文章。
Shell初体验(一) —— Shell入门(一)
变量
1. 变量的命名
一个命名的简单示例
name="dodo"
变量的命名要遵循下面规则
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 中间不能有空格,可以使用下划线 _
- 不能使用标点符号
- 不能使用bash里的关键字(可用help命令查看保留关键字)
2. 变量类型
运行shell时,会同时存在三种变量:
- 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- Shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
3. 只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
先看一个简单的示例
#!/bin/bash
host="www.xxx.com"
readonly host
host="www.aaa.com"
下面我们就执行这个脚本,就会发现报错了
./test.sh: line 5: host: readonly variable
报的是第5行错误,提示信息是host是只读变量
4. 删除变量
使用unset命令可以删除变量,语法:
unset variable_name
下面是一个简单示例
#!/bin/bash
host="www.xxx.com"
unset host
echo $host
我们执行这个脚本./test.sh
就会发现没有任何输出,因为使用unset删除了变量。
5. 变量的使用
变量的使用需要在变量前加上美元符号$,下面就是一个简单示例:
#!/bin/bash
host="www.xxx.com"
echo ${host}
或
echo $host
执行脚本,都会有下面输出:
www.xxx.com
需要说明的是:
{}
这个大括号是非必须的,但是加上是一个好习惯。加花括号是为了帮助解释器识别变量的边界。
可以看下面这个示例
#!/bin/bash
host="www.xxx.com"
echo "This is a $hostname"
这里host变量没有用大括号,解析器就会把hostname
当成一个变量,所以就会有下面的输出
This is a
下面我们加上大括号
#!/bin/bash
host="www.xxx.com"
echo "This is a ${host}name"
接着运行下脚本
This is a www.xxx.comname
可以看见,host被识别为一个已定义变量,可以正常的输出了。
注释
以 # 开头的行就是注释,会被解释器忽略。
Shell
脚本的注释可以使用command + /
,想去掉注释同理。
字符串
1. 字符串的表示
字符串是shell编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号
string='abcdefg'
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
双引号
#!/bin/bash
string="abcdefg"
str="\"$string\"是前7个字母"
echo $str
//输出
"abcdefg"是前7个字母
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
2. 字符串的长度
语法:字符串的长度使用${#string},string是字符串变量名。
看下面一个示例
#!/bin/bash
string="abcdefg"
echo ${#string}
//输出
7
变量为字符串时,${#string} 等价于 ${#string[0]}
:
#!/bin/bash
string="abcdefg"
echo ${#string[0]}
//输出
7
3. 子字符串
可以通过下面语法获取字符串中的子字符串
语法:${string:index:length},这里string是字符串变量,index是下角标,length是要截取的字符串长度。
可以通过下面示例获取子字符串
#!/bin/bash
string="abcdefg"
echo ${string:0:3}
//输出
abc
可以看见,输出从索引0开始的长度为3的子字符串
4. 字符串的拼接
字符串的拼接,可以使用单引号,也可以使用双引号。
双引号拼接
#!/bin/bash
name="liLei"
greeting="hello, nice to meet you, ${name}!"
echo $greeting
#!/bin/bash
name="liLei"
greeting="hello, nice to meet you, "$name"!"
echo $greeting
上面俩种拼接方式的输出都是一样的
hello, nice to meet you, liLei!
单引号拼接
#!/bin/bash
name="liLei"
greeting='hello, nice to meet you, '$name'!'
echo $greeting
hello, nice to meet you, liLei!
再看下面这种形式
#!/bin/bash
name="liLei"
greeting='hello, nice to meet you, ${name}!'
echo $greeting
hello, nice to meet you, ${name}!
后面这种样式,可以说明单引号里这么引用变量是无效的,会被当成字符串,原样输出。
5. 查找字符中字符的位置
expr index方法
语法:expr index string1 string2,在string1中找到string2的位置。
我们看下下面简单示例:
#!/bin/bash
string="hello world"
result=`expr index "$string" ll`
echo $result
我们运行脚本会发现报错了
expr: syntax error
这个提示很好理解,提示意思就是expr有语法错误,但是仔细检查了好几遍并没发现有什么错误。接着我们在终端运行下面命令。
man expr
可以看见一个命令的使用说明,往下拉可以看见下面提示:
STANDARDS
The expr utility conforms to IEEE Std 1003.1-2008 (“POSIX.1”).
The extended arithmetic range and overflow checks do not conflict with POSIX's requirement that arithmetic be done using signed longs, since they
only make a difference to the result in cases where using signed longs would give undefined behavior.
According to the POSIX standard, the use of string arguments length, substr, index, or match produces undefined results. In this version of expr,
these arguments are treated just as their respective string values.
HISTORY
An expr utility first appeared in the Programmer's Workbench (PWB/UNIX). A public domain version of expr written by Pace Willisson <pace@blitz.com>
appeared in 386BSD-0.1.
意思就是
根据POSIX标准,使用字符串参数length,substr,index或match会产生不确定的结果。
在此版本的expr中,这些参数被视为它们各自的字符串值。也就是没有这些方法。
继续查了下资料
bash: "expr index string1 string2" gives "syntax error"
In a bash script, I was trying to use the command
expr index string1 string2
to find the position of string2 in string1, but this does not work on OS X while it works ok on several Linux machines. Reading the man page, I realized expr does something quite different on OS X than on Linux.
https://discussions.apple.com/thread/923299
The expr in Linux is generally GNU expr. Mac OS X uses BSD expr which does not have the index command.
那说明这个index方法在Mac OS上已经不能用了。大家有别的系统的可以在自己机器上尝试下,我就不给大家试了。
awk
我们可以使用awk去匹配,看下面这个示例
#!/bin/bash
echo "This is a test" | awk '{printf("%d\n", match($0, "is"))}'
这个示例很清晰,就是找字符串"This is a test"
中"is"
的索引,这里可以看见"is"
出现了2次,我们运行下,如下输出:
3
可以看见是找到了,并且索引为3,也就是找到的是"This"
中的"is"
,是符合预期的,且索引是从1
开始的。所以:
- 这里是求子字符串所在的第一个符合条件的索引
- 找到则返回指定的正值,找不到符合的则返回0
- 如果可以找到,那索引是从1开始的
后记
本文讲述了Shell中的变量和字符串,感兴趣的给个赞或者关注,有问题的话,欢迎批评留言指正。
网友评论