首页 > 系统相关 >Linux Shell脚本攻略 chapter1------小试牛刀

Linux Shell脚本攻略 chapter1------小试牛刀

时间:2024-07-25 17:12:22浏览次数:13  
标签:文件 Shell 输出 chapter1 echo 命令 tput var 小试牛刀

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命令:通常用于简单的文本处理和格式转换任务,例如批量替换或清理文本中的特定字符或字符集
  • 条件判断运算符
    • 字符串的比较: $str1 = $str2$str1 != $str2空格不能省略
    • 数值的比较:$UID -ne 0同样,空格不能省略
数值比较运算符
-ne:不等于
-eq:等于
-lt:小于
-gt:大于
-le:小于等于
-ge:大于等于
  • if语句
if [ 条件表达式 ]; then  # [ ... ]方括号两边的空格不能省略
  # 条件成立执行的代码
else # 可选
  # 条件不成立执行的代码
fi # 表示if语句的结束
  • 补充内容
    • 获取字符串长度:length=${#var},length就是该字符串的字符数
    • 识别当前的shell版本:echo $SHELLecho $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
  • 浮点数运算
    • 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 # ^运算符计算平方,不用空格

示例

#! /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)的位置,确保标准输出和标准错误输出都写入到同一个地方
  • 补充内容:
    • 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
  • 在脚本中使用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

相关文章

  • shell-awk命令详解(理论+实战)
    一、概述AWK是一种处理文本文件的语言,是一个强大的文本分析工具。它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作数据可以来自标准输入也可以是管道或文件。20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk之所以......
  • 【攻防技术系列+WebShell】检测方式
    一、简介攻击者在入侵企业网站时,通常要通过各种方式获取webshell从而获得企业网站的控制权,然后方便进行之后的入侵行为。常见攻击方式有:直接上传获取webshell、SQL注入、远程文件包含(RFI)、FTP,甚至使用跨站点脚本(XSS)作为攻击的一部分,甚至一些比较老旧的方法利用后台数据库备......
  • Linux入门---(三)Shell编程
    1.脚本格式:#!/bin/bash开头2.脚本执行方式采用bash或sh+脚本的相对路径或绝对路径采用输入脚本的绝对路径或相对路径执行脚本,如./hello.sh在脚本的路径前加上“.”或source(父shell)3.变量系统预定义变量:$HOME,$PWD,$SHELL,$USER等自定义变量:变量名=变量值,如my_var=hello......
  • shell 中设置/取消环境变量
    shell中设置/取消环境变量查看:env设置:export变量名=变量值删除:unset变量名https://blog.csdn.net/mayue_web/article/details/97023615https://www.cnblogs.com/guanbin-529/p/12977662.htmlhttps://cloud.tencent.com/developer/article/1630467https://developer.ali......
  • 在 Python Notebook 中调用 `subprocess` 具有与 `!` shell 不同的 `$PATH`
    我正在IPython笔记本中交互地开发一个包装类。这个包装类调用用java编写的命令行程序,因此我需要访问用于编译该程序的相同版本的java运行时。但是,我注意到在笔记本中使用方便的!运算符,生成的shell实例与在我的终端中使用zsh时不同。这得到了确......
  • 【shell】变量运算
    变量与数字的运算算术运算符指的是可以在程序中实现加、减、乘、除等数学运算的运算符。Shell中常用的数学运算符如下所示。—+:对两个变量做加法。—-:对两个变量做减法。—*:对两个变量做乘法。—/:对两个变量做除法。—**:对两个变量做幂运算。—%:取模运算,第一个变......
  • Liunx-Shell脚本
    shell可以理解为对命令行的一个解释器,命令行输入命令,shell执行,linux系统输出结果1、shell脚本格式开头:#!/bin/bash#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序举例:#!/bin/bashecho"HelloWorld!"echo输出文本命令运行shell脚本必须给其脚本执行......
  • 如何从IBM SOAR连接交换在线powershell?
    有谁知道如何从IBMSOAR连接到ExchangeOnlinePowerShell?我一直在阅读Microsoft文档来检查我可以连接的方式,但它们都是通过powershell执行的命令,我想知道这是否是唯一的方式,我必须通过ssh连接并执行命令,或者是否有是另一种方式。是对的,没有直接从IBMSOAR连接到......
  • 了解package.json中npm run命令的执行原理,以及直接运行shell命令
    了解npmrun在package.json文件中的script字段,可以定义脚本命令,通过npmrun指令运行该脚本。比如简单定义一个输出打印的shell脚本。{"script":{"hw":"echohelloworld!"}}执行npmrunhw可以看到终端上打印出了helloworld!。我们可以在很多工程项目中......
  • 使用shell获取路径参数的最后一个目录层级
    1、填写路径参数时可能会出现最后有多余的"/"场景,所以要先移除可能尾随的斜杠        举例:url=/Walmart-Onn-GTV/wave1/toAmlPatch/        last_dir=${A%/}    echo"$last_dir"结果        /Walmart-Onn-GTV/wave1/toAmlPatch2、使用ba......