1、简介
- 终端提示符
username@hostname$
---$表示普通用户root@hostname#
---#表示超级用户
- shell脚本通常是以 #! 起始的文本文件---
#! /bin/bash
- 运行shell脚本的方式
sh script.sh
将脚本作为 sh 的命令行参数chmod a+x script.sh
和./script.sh
增加可执行权限,让脚本能够独立运行
- ~ 表示home目录的路径
- 在bash中,命令(序列)通过分号或换行符来分隔
$ cmd1 ; cmd2
$ cmd1 \n $ cmd2
,\n表示换行符
- 注释:以 # 为起始
2、终端打印
- echo命令:用于终端打印
- 默认情况,echo会在字符串末尾添加一个换行符
- 使用例子
echo "hello world"
,双引号适合需要变量展开和特殊字符处理的情况echo 'hello world'
,单引号适合作为纯文本输出echo hello world
,可能导致意外的结果,例如echo he;he
这会被看成用分号分隔的两个命令
- printf命令:使用的参数和c语言中的printf函数一样
#!/bin/bash
#filename: printf.sh
printf "%-5s %-10s %-4s\n" No Name Mark
printf "%-5s %-10s %-4.2s\n" 1 Sarath 80.3456
printf "%-5s %-10s %-4.2s\n" 2 James 90.9989
printf "%-5s %-10s %-4.2s\n" 3 Jeff 77.564
- 补充内容:
- -e选项:-e 选项告诉 echo 命令解释特定的转义字符序列,例如\n,不加-e选项,echo命令不会将其解释为换行
- -n选项:-n 选项告诉 echo 命令在输出文本后不要添加换行符
- 彩色输出:使用 echo 命令结合 ANSI 转义码来实现彩色输出。(ANSI 转义码是一种控制字符序列,用于控制终端的文本属性,包括颜色、样式等)
- ANSI 转义码以 \e[ 开头,后面跟着一个或多个参数,以及一个字母作为命令。常见的用于设置文本颜色的 ANSI 转义码形如 \e[参数m,其中 参数 是一个或多个数字,代表不同的颜色和样式。重置颜色,可以使用 \e[0m,它将文本属性恢复为默认状态
- 常见的 ANSI 转义码示例
颜色:
\e[30m - 黑色
\e[31m - 红色
\e[32m - 绿色
\e[33m - 黄色
\e[34m - 蓝色
\e[35m - 紫色
\e[36m - 青色
\e[37m - 白色
背景颜色:
\e[40m - 黑色背景
\e[41m - 红色背景
\e[42m - 绿色背景
\e[43m - 黄色背景
\e[44m - 蓝色背景
\e[45m - 紫色背景
\e[46m - 青色背景
\e[47m - 白色背景
样式:
\e[1m - 粗体
\e[4m - 下划线
\e[5m - 闪烁
示例用法
bash
# 输出红色的粗体文字
echo -e "\e[1;31mThis is bold red text\e[0m"
# 输出蓝色背景的黄色文字
echo -e "\e[44;33mYellow text on blue background\e[0m"
3、玩转变量和环境变量
- 简介
- 在Bash中,每一个变量的值都是以字符串的形式存储
- 环境变量是一种特殊的变量,用于存储系统级或用户级的配置信息和运行时数据
- 一个应用程序执行时,接受一组环境变量
- 每一个变量都是以
name=value
的形式来描述,不能有空格 - 变量赋值:
id=1
,变量取值:$id
,一定要注意这些都是字符形式存储哦(变量的值在Shell中是以字符串形式存储的,但是Shell提供了便捷的数学运算功能,能够自动将包含数字的字符串转换为数值,并进行计算)
- 查看环境变量
- cat命令:
cat /proc/$PID/environ
,$PID表示进程的ID,返回一个环境变量列表,变量间彼此有null(\0)字符分割cat /proc/12501/environ | tr '\0' '\n'
,将分割符替换成换行符,更易读
- tr命令:通常用于简单的文本处理和格式转换任务,例如批量替换或清理文本中的特定字符或字符集
- cat命令:
- 条件判断运算符
- 字符串的比较:
$str1 = $str2
和$str1 != $str2
,空格不能省略 - 数值的比较:
$UID -ne 0
,同样,空格不能省略
- 字符串的比较:
数值比较运算符
-ne:不等于
-eq:等于
-lt:小于
-gt:大于
-le:小于等于
-ge:大于等于
- if语句
if [ 条件表达式 ]; then # [ ... ]方括号两边的空格不能省略
# 条件成立执行的代码
else # 可选
# 条件不成立执行的代码
fi # 表示if语句的结束
- 补充内容
- 获取字符串长度:
length=${#var}
,length就是该字符串的字符数 - 识别当前的shell版本:
echo $SHELL
或echo $0
- 检查是否为超级用户
- UID:用于检查当前脚本是以超级用户还是普通用户运行的环境变量,root用户的UID是0
- 获取字符串长度:
变量使用示例
#!/bin/bash
#filename: variables.sh
fruit=apple
count=5
string="\e[1;31mWe have ${count} ${fruit}(s)\e[0m"
echo -e ${string}
echo ${#string}
检查是否为超级用户示例
#!/bin/bash
#filename: isRoot.sh
if [ $UID -ne 0 ]; then
echo "Non roor user. Please run as root."
else
echo "Root user."
fi
4、通过shell进行数学运算
- 命令置换
- $(command): 获取command命令的结果
- 整数运算
- expr命令: 用于表达式求值,
result=$(expr 算术表达式)
- 算术表达式和操作符之间需要有空格分隔
- 乘法运算符 * 需要使用反斜杠 * 进行转义,以避免被Shell解释为文件通配符
- 双括号(()):可以执行更复杂的整数运算,并支持变量的引用,
result=$(( a * b + 5 )) # 其中a=10 b=3
,注意空格- 表达式中的变量直接使用,无需使用 $ 符号引用
- 如果需要进行赋值操作,可以直接将表达式赋给变量,例:
result=((a * b + 5)) # 其中a=10 b=3
- expr命令: 用于表达式求值,
- 浮点数运算
- bc命令:
result=$(echo 数学表达式 | bc)
- 处理逻辑:例
echo "3.5 + 2.1" | bc
- 表达式传递给 bc: 这里的 echo "3.5 + 2.1" 将字符串 "3.5 + 2.1" 输出到标准输出。然后,管道 | 将这个输出作为 bc 命令的输入
- bc 计算结果: bc 命令收到输入后,会解析并计算表达式 "3.5 + 2.1",得出结果 5.6
- 输出到标准输出: bc 计算完成后,将结果 5.6 输出到标准输出(可以使用命令置换$()获取bc命令的输出 )
- bc命令补充内容:
- 设定小数精度:例
echo "scale=3; 数学表达式" | bc # 调节scale的值来确定保留的小数位数
- 进制转换:例
echo "obase=10;obase=2;数学表达式" | bc
,obase表示output base(输出结果的进制),ibase表示input base(输入的进制),二者默认都为10 - 计算平方以及平方根:例
echo "sqrt(100) | bc" # sqrt()计算平方根
,echo "10^2" | bc # ^运算符计算平方,不用空格
- 设定小数精度:例
- bc命令:
示例
#! /bin/bash
# filename: math.sh
no1=4
no2=5
add_result=$(( no1 + no2 ))
sub_result=$(( no1 - no2 ))
mul_result=$(( no1 \* no2 ))
div_result=$(expr $no1 / $no2)
echo -e "\e[1;31m整数四则运算\e[0m"
echo -e "${add_result}\t${sub_result}\t${mul_result}\t${div_result}"
result=`echo "$no2 * 1.64" | bc`
echo $result
result1=`echo "scale=2;3/8" | bc`
echo $result1
# 进制转换
no=`echo "obase=2;$no1" | bc`
echo $no
echo "obase=10;ibase=2;$no" | bc
5、玩转文件描述符和重定向
- 文件描述符:与文件输入输出相关联的整数,用来跟踪已打开的文件,三个常见的文件描述符
- 标准输入(stdin): standard input---0
- 标准输出(stdout): standard output---1
- 标准错误(stderr): standard error---2
- 重定向操作符
- 输出重定向 > : 等同于1>,将命令的标准输出重定向到文件,如果文件不存在则创建该文件,如果文件已存在则覆盖其内容,例
ls > filelist.txt
- 追加输出重定向 >> : 将命令的标准输出以追加方式重定向到文件,如果文件不存在则创建该文件,例
echo "Hello, World!" >> greetings.txt
- 输入重定向 < : 将文件的内容作为命令的标准输入,例
wc -l < file.txt
,这个命令将 file.txt 文件的内容作为 wc -l 命令的输入,统计文件中的行数 - Here Document << : 允许在脚本中嵌入多行文本块,并将其作为命令的输入。常用于向命令提供多行数据输入,例
cmd << EOF
表示在EOF标记之前的所有行作为cmd命令的输入,这个标记是自定义的 - 2> : 将命令的标准错误输出重定向到文件或其他位置
- 2>&1 : 用于将标准错误输出(stderr,文件描述符为2)重定向到标准输出(stdout,文件描述符为1)的位置,确保标准输出和标准错误输出都写入到同一个地方
- 输出重定向 > : 等同于1>,将命令的标准输出重定向到文件,如果文件不存在则创建该文件,如果文件已存在则覆盖其内容,例
- 补充内容:
- tee命令:从标准输入读取数据,并将其复制到标准输出以及一个或多个文件中,在需要同时查看输出和保存输出到文件时非常有用,-a选项表示追加
- 自定义文件描述符: 使用exec命令创建自定义的文件描述符,文件打开模式(只读、截断、追加...),0 1 2这三个是预留描述符,不能用这三个数自定义
exec 3< input.txt # 只读模式打开文件,文件描述符为3
cat <&3 # 读取文件描述符为3的文件
exec 4> output.txt # 截断模式打开文件,文件描述符为4
echo newline >&4 # 将newline覆盖写入文件
exec 5>> output.txt # 追加模式打开文件,文件描述符为5
echo appendline >&5 # 将appendlline追加写入文件
6、数组和关联数组
- 定义数组:
- 在单行中使用一列值来定义:
array_var=(1 2 3 4 5 6)
- 将数组定义成一组索引-值:
array_var[0]=1
- 在单行中使用一列值来定义:
- 数组的打印:
- 打印特定索引的数组元素:
echo ${array_var[0]}
- 以清单形式打印数组的所有元素:
echo ${array_var[*]}
- 打印数组的长度:
echo ${#array_var[*]}
- 打印特定索引的数组元素:
- 关联数组
- 注:普通数组只能用整数做为索引,关联数组可以用任意的文本作为数组索引
示例
#! /bin/bash
# filename: array_var.sh
# 使用一列值定义数组
array_var=(1 2 3 4 5 6)
echo ${array_var[*]} # 打印所有数组元素的值
echo ${!array_var[*]} # 打印所有数组元素的索引
echo ${#array_var[*]} # 打印数组长度
# 定义关联数组
declare -A fruits_value # 声明关联数组
fruits_value=([apple]='100 dollars', [orange]='150 dollars')
# 也可以这么赋值
# fruits_value[apple]='100 dollars'
# fruits_value[orange]='150 dollars'
echo "Apple costs ${fruits_value[apple]}"
echo ${!fruits_value[*]}
7、使用别名
- alias命令:
alias new_cmd='cmd sequence'
,创建别名,这只是暂时的,如果想要永久有效,就要将其写入shell的配置文件中,如echo 'alias new_cmd="cmd sequence"' >> ~/.bashrc
- unalias命令:移除一个或多个别名,-a选项移除所有定义的别名
- 对别名进行转义:
\command
,相当于关闭了别名
8、获取终端信息
- tput命令:
tput longname
,获取终端类型tput lines
,获取终端行数tput cols
,获取终端列数tput setb no
,设置终端背景色,no可以在0-7之间取值tput serf no
,设置文本前景色,no可以在0-7之间取值tput bold
,设置文本样式为粗体tput smul; tput rmul
,设置下划线的起止tput cup 5 4
,将光标定位在5行4列处tput sc
,保存当前光标位置tput rc
,恢复保存的光标位置tput ed
,删除当前光标位置到行尾的所有内容
- stty命令:
stty -echo
,禁止将输出发送到终端stty echo
,允许将输出发送到终端
9、获取、设置日期和延时
- date命令:
- 读取日期:
date
- 打印纪元时:
date +%s
,计算两个日期或两段时间的差值 - 将日期串转换成纪元时:
date --date "日期串" +%s
,--date选项用于提供日期串作为输入,+%s是日期格式化选项,表示纪元时 - 打印特定格式的日期:
date "+%d %B %Y"
,用格式串结合 + 作为date命令的参数 - 设置日期和时间:
date -s "格式化的日期串"
- 读取日期:
#! /bin/bash
# filename: time_take.sh
# 检查一组命令所花费的时间
start=$(date +%s)
# commands or statements
echo "Print this sentence."
end=$(date +%s)
difference=$((end - start))
echo "Time taken to execute commands is $difference seconds."
- 在脚本中生成延时:tput sc和tput rc和tput ed 常用来创建动态更新的输出
#! /bin/bash
# filename: sleep.sh
# tput sc和tput rc和tput ed常用来创建动态更新的输出
echo -n Count:
tput sc # 保存当前光标位置
count=0;
while true; # 无限循环
do # 表示在条件为真时执行的命令块的开始
if [ $count -lt 40 ];
then
let count++;
sleep 1;
tput rc # 恢复保存的光标位置
tput ed # 清除从当前光标位置到行尾的内容
echo -n $count;
else
exit 0; # 退出脚本,退出码为0表示正常退出
fi # 表示条件语句的结束
done # 表示命令块的结束,回到 while 关键字处重新评估 condition
10、调试脚本
- 启用调试模式:
- 在Shell脚本的开头加入以下行可以启用调试模式:
#!/bin/bash -x
- 在脚本执行时,可以使用 -x 参数来启用调试模式:
bash -x script.sh
- 在Shell脚本的开头加入以下行可以启用调试模式:
- 在脚本中使用set built-in来启用或禁止调试打印:
- set -x: 在执行时显示参数和命令
- set +x: 禁止调试
- set -v: 当命令进行读取时显示输入
- set +v: 禁止打印输入
- 自定义格式显示调试信息:通过传递 _DEBUG 环境变量来建立这类调试风格
#! /bin/bash
# filename: debug1.sh
# 自定义格式显示调试信息
function DEBUG()
{
[ "$_DEBUG" == "on" ] && $@ || : # 命令: 告诉shell不进行任何操作
}
for i in {1..10}
do
DEBUG echo $i # 打印的调试信息
done
在需要打印调试信息的语句前加上 DEBUG ,把 _DEBUG=on 传递给脚本打印调试信息,否则不打印。_DEBUG=on ./script.sh
11、函数和参数
- 定义函数:
function fname() # function 可以省略
{
statements;
}
- 执行函数:使用函数名调用函数,可以传递参数
fname ; # 执行函数
fname arg1 arg2 ; # 传递参数
- 访问函数参数:
$n表示第n个参数($1表示第一个参数)
"$@"等价于 "$1" "$2" ... "$n" # 列表的形式
""$*等价于 "#1c$2c$3c..$n",c表示IFS的第一个字符,所有参数被当做单个字符串
- 导出函数:
export -f fname
,和环境变量一样,函数作用于可以扩展到子进程中 - 读取命令返回值(状态):$? 会给出命令的返回值,0表示正常,非0失败
#! /bin/bash
# filename: success_test.sh
CMD="echo command_test"
status
$CMD
if [ $? -eq 0 ];
then
echo "$CMD executed successfully"
else
echo "$CMD terminated unsuccessfully"
fi
12、读取命令序列的输出
- 命令替换(子shell): $(command)
- 反引用:`command`
- 利用子shell生成一个独立的进程
#! /bin/bash
# 利用子shell生成一个独立的进程
# 可以使用()操作符来定义一个子shell
pwd
(cd /bin; ls) # 当命令在子shell中执行时,所有改变仅限于子shell内
pwd
- 通过引用子shell的方式来保留空格和换行符
#! /bin/bash
# 通过引用子shell的方式来保留空格和换行符
cat out.txt
out=$(cat out.txt)
echo $out # 丢失换行符
echo "$out" # 加双引号保留空格和换行符
13、以不按回车键的方式读取字符"n"
- read命令
# 以不按回车键的方式读取字符"n"
# 读取指定数量的字符
read -n 3 var
echo $var
# 显示提示信息
read -p "enter input:" var
# 用不回显的方式读取密码
read -s var
# 在特定时限内读取输入 read -t timeout var
read -t 2 var # 2秒内
# 用定界符结束输入行 read -d delim_char var
read -d ":" var
14、字段分隔符和迭代器
- IFS:存储定界符的环境变量,默认值为空白字符
- 序列的生成
{1..100}
表示1到100的数字序列{a..z}或{A..Z}或{a..h}
表示字符序列
- 循环
# for循环
for var in list
do
statement;
done
# while循环
while condition # while true 为无限循环
do
statement;
done
# until循环,一直执行知道给定的条件为真
until condition
do
statement;
done
15、比较与测试
- [ condition ]:[]运算符表示测试命令
- 多个条件测试(连接多个条件)
- -a:逻辑与
- -o:逻辑或
[ condition1 -a condition2 -o condition3 ]
[ condition1 ] && [ condition2 ] || [ condition3 ]
或
[[ condition1 && condition2 || condition3 ]]
-a和-o与&&和||的区别:
用途不同:
-a 和 -o 用于在条件测试中进行逻辑连接。
&& 和 || 用于在命令执行流程中进行逻辑控制。
使用对象不同:
-a 和 -o 用于 [ ] 中的测试表达式。
&& 和 || 用于命令行中的命令和操作。
操作对象不同:
-a 和 -o 操作条件测试的结果,返回布尔值。
&& 和 || 操作命令执行的结果,返回命令的执行状态。
- if-else嵌套语句
if condition;
then
statement;
else
statement;
fi
# 逻辑运算符简化
[ condition ] && action; # 条件为真,执行action
[ condition ] || action; # 条件为假,执行action
- 算术比较:详见第3节数值比较运算符
- 字符串比较:
$str1 = $str2 # 判断是否相同
$str1 != $str2 # 判断是否不相同
$str1 > $str2 # 判断字符序的大小
$str1 < $str2
-z $str # str为空,返回真
-n $str # str为非空,返回真
- 文件系统的测试:
[ -f "$file" ]:检查文件是否为普通文件。
[ -d "$dir" ]:检查目录是否存在。
[ -r "$file" ]:检查文件是否可读。
[ -w "$file" ]:检查文件是否可写。
[ -x "$file" ]:检查文件是否可执行。
[ -s "$file" ]:检查文件是否存在且非空。
[ -e "$file" ]:检查文件是否存在。
[ "$file1" -ef "$file2" ]:检查两个文件是否是同一个文件。
[ "$file1" -nt "$file2" ]:检查文件 $file1 是否比文件 $file2 更新。
[ "$file1" -ot "$file2" ]:检查文件 $file1 是否比文件 $file2 更旧。
[ -u "$file" ]:检查文件或目录是否有SUID位设置。
标签:文件,Shell,输出,chapter1,echo,命令,tput,var,小试牛刀
From: https://www.cnblogs.com/winter-z/p/18314575