文章目录
- shell
- 变量
- 全局变量(环境变量)
- 局部变量
- 设置PATH 环境变量
- 修改变量属性
- 启动文件
- 环境变量持久化
- ./和. 的区别
- 脚本编写
- 重定向
- 判断 和循环
- 命令行参数
- 传入参数
- 循环读取命令行参数
- 获取用户输入
- 处理选项
- 处理简单选项
- 处理带值选项
- 重定向
- 显示并且同时输出到文件
- 替换目录下的所有文件中某个关键字
- 删除关键字所在行
shell
shell的作用是将我们输入的命令与内核沟通。
linux默认使用的是bash shell
echo $SHELL
可以查看当前使用的shell版本
shell中如果想一次执行多条命令,可以用分号隔开,多条命令的组合可以放到一个文件中,我们把它叫做脚本。
date ; cd
这样就编写了一个非常简单的shell脚本。
变量
存储shell会话和工作环境的相关信息。
环境变量存储在内存中,以便shell中运行的脚本和程序能够访问。
环境变量分为:全局变量和局部变量
全局变量:对当前shell以及所有子shell可见
局部变量:只在当前shell可见,子shell不可见
所以全局变量和局部变量差异就是是否 可以被子进程使用
全局变量(环境变量)
set 查看当前shell所有变量,包括全局和局部
env 查看当前shell下所有环境变量(只能查看全局变量)
printenv HOME 查看某个全局环境变量的值
echo $HOME
查看环境变量
echo $$
查看当前shell的pid
export作用是将局部变量转换成全局变量
export my_all_home=/lib/lib
设定全局环境变量
子shell可以查看和使用但不能修改父shell中的全局环境变量
unset my_all_home 删除环境比哪里
局部变量
没有命令能够查看所有局部变量
设定局部变量 myhome=/lib/
查看某个局部变量
变量内若有空格可以使用双引号或者单引号myhome=/lib/ jj
设置PATH 环境变量
当输入一个外部命令时,shell会搜索系统从中找到对应程序。
PATH环境变量定义了用于查找命令和程序的目录。
如果要执行的外部命令在PATH中查找不到应用程序,则会报错。
如果要在PATH后继续添加路径,我们可以使用冒号累加
export PATH=$PATH:/lib
修改变量属性
变量默认是字符串类型
可以使用declare改变变量类型
declare -a var
将变量修改为数组类型
启动文件
- 在系统的启动shell中会启动/etc/profile 一旦启动shell就会执行该文件中的命令
- HOME目录下的启动文件。在启用一个新shell时会用到下面的启动文件
ls -a home目录可以看到
./bashrc ubuntu的home目录启动文件
环境变量持久化
所以./bashrc文件的作用就是我们可以将要使用的全局环境变量放到这个文件中,那么我们一旦开启新的shell则自动拥有这个环境变量
如果不想重启立即生效,则执行source ~/.bashrc
./和. 的区别
-
点空格斜杠执行脚本,是相当于source 执行脚本,也就是说在当前进程中执行命令,所以其中所有变量的设置会对当前Shell其作用。
-
点斜杠执行脚本是外部命令,所以他会启动子进程然后运行,所以一些局部变量就不起作用。
也就是说设置环境变量的时候我们使用source或者说. 空格可以直接生效。
脚本编写
使用shell脚本文件,必须在第一行指明所使用的shell版本
#!/bin/bash
表示使用的是bash shell
#!/bin/bash
date
# 打印字符串
echo "let's go"
# 将下一行打印到当前行连到一起
echo -n "let's go at:"
date
# 打印环境变量,两种均可
echo "HOME: $HOME"
echo "user: ${USER}"
# 用户自定义变量,只在本脚本中生效
var1=10
echo "var1= $var1"
var2=$var1
echo "var2= $var2"
# 将shell的输出赋值给变量
var_date=`date`
echo "$var_date"
重定向
输出重定向到文件
date > test1.txt 覆盖
date >> test1.txt 追加
如果想把一个命令的输出作为另一个命令的输入,可以使用重定向
date > 1.log
sort < 1.log
但是需要两条命令, 看起来有点笨拙。
使用管道符则可以直接完成这个功能
date | sort
判断 和循环
# if后面的命令执行成功返回0,则可以进入then
if date
then
echo "date works"
else
echo "date not work"
fi
# if后面只能跟命令,如果要进行条件判断则需要加大括号
if [ 1 -eq 2 ]
then
echo "1 = 2"
else
echo "1 != 2"
fi
# while
var2=5
while [ $var2 -gt 0 ]
do
echo "$var2 test"
var2=$[ $var2-1 ]
done
# for var in list 读取列表
for i in Ala Alb Alc
do
echo "test: $i"
done
list="Ala Alb Alc"
if date
then
echo "date works"
else
echo "date not work"
fi
# if后面只能跟命令,如果要进行条件判断则需要加大括号
if [ 1 -eq 2 ]
then
echo "1 = 2"
else
echo "1 != 2"
fi
# while
var2=5
while [ $var2 -gt 0 ]
do
echo "$var2 test"
var2=$[ $var2-1 ]
done
# for var in list 读取列表
for i in Ala Alb Alc
do
echo "test: $i"
done
list="Ala Alb Alc"
for i in $list
do
echo "test: $i"
done
# for in c style
for ((i=1; i<10; i++))
do
echo "for in c $i"
done
# for遍历目录
for file in /home/*
do
if [ -d "$file" ]
then
echo "$file is a dir"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
命令行参数
传入参数
对传入参数检查,如果缺少参数会产生很糟糕的结果
# args
echo $0 #./1.sh 不单单是程序名称
echo $1
if [ -n "$2" ] # 如果有参数2
# if [ -z "$2" ] 如果没有参数2
then
echo $2
else
echo no args 2
fi
循环读取命令行参数
#当前进程pid
# $$
#统计参数个数
echo "param count $#"
for param in "$*"
do
echo "Parameter * = $param"
done
for param in "$@"
do
echo "Parameter @ = $param"
done
./1.sh a b c d
param count 4
Parameter * = a b c d
Parameter @ = a
Parameter @ = b
Parameter @ = c
Parameter @ = d
获取用户输入
当执行脚本到后,还可以使用read在脚本运行中获取用户输入以做下一步判断。
处理选项
处理简单选项
遍历所有选项,选择符合条件的
while [ -n "$1" ] #循环检测第一个参数,如果第一个参数存在则进入循环
do
case "$1" in
-a) echo "found the -a option";; # 双引号为语法
-b) echo "found the -b option";;
-c) echo "found the -c option";;
*) echo "no matching option";; # 默认序列
esac # case结束符
shift # 将参数左移一个位置
done
(base) [user1@sysqa-h3c-b10 ~]$ ./1.sh -b -c -d -a
found the -b option
found the -c option
no matching option
found the -a option
处理带值选项
脚本检测选项中附加的参数,然后进行处理
while [ -n "$1" ] #循环检测第一个参数,如果第一个参数存在则进入循环
#while [ $# -gt 0 ] # 也可以使用这个判断,如果参数个数非0
do
case "$1" in
-a) echo "found the -a option";; # 双引号为语法
-b) param="$2"
echo "found the -b option, param=$param"
shift;; #因为加了个参数所以要移一位
-c) echo "found the -c option";;
--) shift #发现破折号,则选项列表结束,脚本将剩余参数作为参数而不是选项处理
break;; #退出循环去处理剩余参数
*) echo "no matching option";; # 默认序列
esac # case结束符
shift # 将参数左移一个位置
done
(base) [user1@sysqa-h3c-b10 ~]$ ./1.sh -a -b 4 -d -c
found the -a option
found the -b option, param=4
no matching option
found the -c option
#!/bin/bash
# 定义长短选项
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
echo "Usage: $0 [-o|--output=FILE] [-v|--verbose] [file...]"
echo " -o, --output=FILE Specify output file"
echo " -v, --verbose Enable verbose mode"
echo " -h, --help Display this help message"
exit 0
;;
-o|--output)
shift # 跳过选项本身
output_file="$1"
shift # 跳过值
;;
-v|--verbose)
verbose_flag=true
;;
--) # 结束选项解析
shift
break
;;
*) # 未知选项
echo "Error: Unknown option $1"
exit 1
;;
esac
shift # 跳过当前参数
done
# 检查是否提供了至少一个非选项参数
if [ $# -eq 0 ]; then
echo "Error: No input files provided."
echo "Usage: $0 [-o|--output=FILE] [-v|--verbose] [file...]"
exit 1
fi
# 处理非选项参数(这里简单打印出来)
echo "Processing files:"
for file in "$@"; do
echo " $file"
# 在这里可以添加处理文件的代码,例如使用cat, grep, sed等命令
done
# 根据选项执行相应的操作
if [ -n "$output_file" ]; then
echo "Output file specified: $output_file"
# 在这里可以添加将处理结果写入文件的代码
fi
if $verbose_flag; then
echo "Verbose mode is enabled."
# 在这里可以添加冗余输出的代码
fi
# 脚本结束
exit 0
重定向
标准输入是键盘
输入重定向符号为 < ,也就是输入不再从键盘,而是从其他地方比如文件
标准输出是显示器
输出重定向符号为 >, 也就是输出不再到显示器二十到其他地方比如文件
使用 >> 重定向输出追加
标准错误输出
shell是将错误消息与正常输出分开处理,所以如果发生错误,还是会输出到屏幕
ls badfile 2> a.txt
可以将标准错误输出到文件
数据和错误同时输出到一个文件
ls badfile &> a.txt
数据和错误分别输出
ls badfile 1> a.txt 2>b.txt
显示并且同时输出到文件
tee命令
date | tee 1.txt
如果希望追加则加 -a
替换目录下的所有文件中某个关键字
#!/bin/bash
# find path and replace all .c file keywords is "while" to "for"
find ./ -name "*.c" -exec sed -i 's/hip/mc/g' {} \;
删除关键字所在行
find ./ -name "*.c" -exec sed -i '/load_json_helper/d' {} \;