Shell脚本常用
作为一个运维工程师(数据库工程师) ,管理和维护成百上千台服务器是很正常的事情,脚本就成为了
不可或缺的工具,shell是最基本的了,工作中经常用到,自己讲偶尔犯错的部分记录一下,警示自己。
另外,shell 是Linux原生的交互工具,使用方便,简单,可以在运维工作中 ,大大的提高工作效率
,对日常简单的任务都可以由shell处理 , 哈哈 。 当然也有不合适的地方。比如说:
需要比数组更复杂的数据结构
出现了复杂的转义问题
有太多的字符串操作
性能问题
任务代码比较多 ...
注意 : 这个时候 选择 Python 会是一个明智的选择
shell 工作中易错总结
1.字符串单引号和双引号 ‘’ “”
a. 单引号内部的 变量 是完全按照字符展示的,不会替换成为变量的值的。
b. 双引号中的变量会进行变量值替换。
#!/bin/bash
for x in $( seq 1 10 )
do
echo '$x : ' ," $x !"
done
输出:
$x : , 1
$x : , 2
$x : , 3
$x : , 4
$x : , 5
$x : , 6
$x : , 7
$x : , 8
$x : , 9
$x : , 10
2. 反引号和$()的使用
和 $() 是对等的,但是后者更清晰,特别是多层次嵌套的时候。 反单引号在有些字体里
跟正单引号很相似。 $()能够内嵌使用,而且避免了转义符的麻烦。
for x in $( seq 1 10 ) 和 for x in `seq 1 10 ` 是对等的
比如要是 输出 : 1-2-3-4 。 明显第二个更加简单方便,并且不需要转义
echo "1-`echo 2-\`echo 3-\\\`echo 4\\\`\``"
echo "1-$(echo 2-$(echo 3-$(echo 4)))"
3. 从文件中按照行级别读取
以下三个方式都可以的
3.1 while
while read line
do
echo $line
done < test
3.2 cat | while
cat filename | while read line
do
echo $line
done
3.3 for
注意 此方式在行中有空格的时候 会变为多行
for line in `cat filename `
do
echo $line
done
4. 变量 variable
整数变量加减乘除运算 , 这个我经常记混,所以特别记录以下
for x in ` seq 1 10 `
do
echo $x " " $((${x} + 10)) " " $(($x * 10))
done
输出 :
1 11 10
2 12 20
3 13 30
4 14 40
5 15 50
6 16 60
7 17 70
8 18 80
9 19 90
10 20 100
5. function ,shell 定义函数非常方便
把相同的功能模块定义为function , 可以提高代码的重用性和可读性,如下读取文件代码 :
1 | GetFileLines() { |
6. 用[]替代[]
使用[[]]能避免像异常的文件扩展名之类的问题,而且能带来很多语法上的改进
,而且还增加了很多新功能:
操作符 功能说明
|| 逻辑or(仅双中括号里使用)
&& 逻辑and(仅双中括号里使用)
< 字符串比较(双中括号里不需要转移)
-lt 数字比较
= 字符串相等
== 以Globbing方式进行字符串比较(仅双中括号里使用,参考下文)
=~ 用正则表达式进行字符串比较(仅双中括号里使用,参考下文)
-n 非空字符串
-z 空字符串
-eq 数字相等
-ne 数字不等
单中括号:
[ $x -gt 3 ]
双中括号
[[ $x > 3 ]] #右侧如果是变量比较,一定要加上双引号
正则表达式
使用双中括号带来的好处用下面几个例子最能表现:
t="abc123"
[[ "$t" == abc* ]] # true (globbing比较)
[[ "$t" == "abc*" ]] # false (字面比较)
[[ "$t" =~ [abc]+[123]+ ]] # true (正则表达式比较)
[[ "$t" =~ "abc*" ]] # false (字面比较)
注意,从bash 3.2版开始,正则表达式和globbing表达式都不能用引号包裹。如果你的表达式里有空格
,你可以把它存储到一个变量里:
r="a b+"
[[ "a bbb" =~ $r ]] # true
按Globbing方式的字符串比较也可以用到case语句中:
case $t in
abc*) <action> ;;
esac
7. 字符串操作
1 | ${#string} $string的长度 |
Bash里有各种各样操作字符串的方式
基本用户
1 | f="path1/path2/file.ext" |
替换操作
1 | f="path1/path2/file.ext" |
删除头部或尾部
1 | f="path1/path2/file.ext" |
8.分割字符串
假设变量$str的值为foo-bar-baz,如果你想按-分割成多个段并遍历它,可以使用read命令,
并且设置 IFS 的值为-:
$ IFS=- read -r x y z <<< "$str"
这里我们使用read x命令从标准输入读取内容,分割后并依次保存到x y z变量中。其中,$x 为foo,
$y 为 bar, $z 为 baz。 另外要留意的一处是here-string操作符<<<,可以很方便地将字符串传递
给命令的标准输入。在这个例子中,$str的内容传给 read 命令的标准输入。
你也可以将分割后的几个字段保存到数组类型的变量中:
$ IFS=- read -ra parts <<< "foo-bar-baz"
在这里,-a 选项告诉read命令将分割后的元素保存到数组parts中。随后,你可以通过${parts[0]}
${parts[1]}和${parts[0]}来访问数组的各个元素,或者通过${parts[@]}来访问所有元素。
9. 转换大小写
使用tr 命令替换
10.去除行尾的最后一个字符
awk -F "" -v OFS="" '$NF="" {print}1'
总结
1 | shell 使用比较方便,系统原生,属于轻量级脚本,但是不得不承认,语法上面不如Python 简洁,另外shell 用起来很多地方容易出错。 |