shell入门
脚本格式入门
脚本以!/bin/bash
开头,指定解析器
第一个shell脚本
需求
创建shell脚本,输出helloword
实现
touch helloword.sh
vim helloword.sh
# 在helloword中输入以下内容
#!/bin/bash
echo "hello word"
脚本的常用执行方式
注意:bash执行本质是bash解析器执行脚本,所以不需要执行权限;第二种执行方式本质是脚本自己执行,所以需要执行权限。
采用bash或sh
# sh
sh helloword.sh
# bash
bash helloword.sh
采用输入脚本的路径
# 必须赋予脚本执行权限
chmod +x helloword.sh
# 相对路径
./helloword.sh
# 绝对路径
/Users/kuma/helloword.sh
第二个shell脚本:多命令处理
需求
在/Users/kuma目录下创建一个test.txt,在该文件中增加“this is a test”
实现
touch test.sh
vim test.sh
# 在test.sh中输入如下内容
#!bin/bash
cd /Users/kuma
touch test.txt
echo "this is a test" >> test.txt
shell中的变量
系统变量
$SHELL;$PWD;$USER
等
案例
查看系统变量的值
echo $HOME
显示当前shell中的所有变量
set
自定义变量
基本语法
- 定义变量:变量=值
- 撤销变量:unset 变量
- 声明静态变量:readonly变量。不能unset
变量定义规则
- 变量不能以数字开头,环境变量名称建议大写
- 等号两侧不能有空格
- 在bash中,变量默认都是字符串类型,无法直接进行数值运算
- 变量的值如果有空格,需要使用双引号或者单引号括起来
案例
# 定义变量A
A=10
# 给变量重新赋值
A=20
# 撤销变量
unset A
# 声明静态变量B,不能unset
readonly B=10
# 变量的值如果有空格,需要使用引号
A="this is a test"
# 可以把变量提升为全局变量,可供其他shell程序使用
export A
特殊变量:$n
基本语法
$n
:n为数字,$0
代表该脚本的名称,$1 - $9
代表第1到第9个参数。10以上的参数需要用大括号包含,比如:${10}
。
案例
输出该脚本的文件名称,输入参数1和输入参数2的值
touch para.sh
vim para.sh
# 输入
#!bin/bash
echo "$0 $1 $2"
# 执行
bash para.sh one two
特殊变量:$#
基本语法
$#
:获取所有参数的个数,常用于循环
案例
vim para.sh
# 输入
echo "$0 $1 $2"
echo $#
特殊变量:$*;$@
基本语法
-
$*
:代表所有的参数,把所有的参数当作一个整体 -
$@
:代表所有的参数,把所有的参数区分对待
案例
vim para.sh
#!bin/bash
echo $0 $1 $2
echo $#
echo $*
echo $@
# 执行
bash para.sh 1 2 3
特殊变量:$?
基本语法
$?
:最后一次执行的命令返回状态。如果正确执行,则返回0;反之返回非0
案例
判断helloword.sh脚本是否正确运行
bash helloword.sh
echo $?
运算符
基本语法
-
$((运算式))
或者$[运算式]
-
expr +;-;\*;/;%
:expr
运算符之间要有空格
案例
计算3+2
expr 2 + 3
计算(3+2)*4
expr `expr 3 + 2` \* 4
res=$[(3+2)*4]
条件判断
基本语法
[ condition ]
,注意:condition
前后要有空格;条件非空即为true
;[ yowai ]
返回ture
;[]
返回false
常用判断条件
两个整数之间的比较
符号 | 意义 |
---|---|
= |
字符串比较 |
-lt |
小于 |
-le |
小于等于 |
-gt |
大于 |
-ge |
大于等于 |
-eq |
等于 |
-ne |
不等于 |
按照文件权限判断
符号 | 意义 |
---|---|
-r |
可读 |
-w |
可写 |
-x |
可执行 |
按照文件类型判断
符号 | 意义 |
---|---|
-f |
文件存在并且是常规文件(file) |
-e |
文件存在 |
-d |
文件存在并且是目录(directory) |
案例
# 23是否大于等于22
[ 23 -ge 22 ]
# helloword.sh是否有写的权限
[-w helloword.txt ]
# /Users/kuma/shell/helloword.txt是否存在
[ -e /Users/kuma/shell/helloword.txt ]
# 多条件判断:「&&」表示前一个执行成功后执行后者;「||」表示前者失败后执行后者
[ -e /Users/kuma/shell/helloword.txt ] && echo ok || echo notOk
流程控制
基本语法(if)
if [ condition ];then
程序主体
if
注意:
-
[ condition ]
中括号和条件判断之间必须有空格 -
if
后要有空格
案例
输入一个数字,如果是1,则输出this is one;如果是2,则输入this is two;如果是其他,则什么都不输出。
#!/bin/bash
if [ $1 -eq 1 ]
then
echo "this is one"
elif [ $1 -eq 2 ]
then
echo "this is two"
fi
基本语法(case)
case $变量名 in
"值1")
如果变量的值是1,则执行程序1
;;
"值2")
如果变量的值是2,则执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
esca
注意:
- case行尾必须为单词in;每一个模式匹配必须以右括号
)
结束 - 双分号
;;
表示命令序列结束,相当于break
- 最后的
*)
表示默认模式,相当于default
案例
输入一个数字,如果是1,则输出this is one;如果是2,则输入this is two;如果是其他,则什么都不输出。
#!/bin/bash
case $1 in
1)
echo "this is one"
;;
2)
echo "this is two"
;;
*)
echo "this is other"
;;
esac
for循环
基本语法-1
for ((初始值;循环控制条件;变量变化))
do
程序
done
案例-1
从1累加到100
#!/bin/bash
s=0
for ((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
基本语法-2
for 变量 in 值1 值2 值3 ...
do
程序
done
案例-2
打印所有参数
#!/bin/bash
for i in $*
do
echo "thi
done
比较$*
和$@
的区别
-
$*
和$@
都表示传递给函数或脚本的所有参数,不被双引号包含的时候,都以$1;$2...
的形式输出所有参数 - 当被双引号包住的时候
$*
会将所有参数当成一个整体;$@
会将参数区别对待
# $*
vim test_01.sh
#!/bin/bash
for i in "$*"
do
echo "i love $i"
done
# $@
vim test_02.sh
#!/bin/bash
for i in "$@"
do
echo "i love $i"
done
while循环
基本语法
while [ 条件判断 ]
do
程序
done
案例
从1加到100
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
read读取控制台
基本语法
read [选项] (参数)
:
-
-p
:指定读取值的提示符 -
-t
:指定读取值等待的时间
案例
提示7s内,读取控制台的输入的名称
vim read.sh
#!/bin/bash
read -t 5 -p "input your name" name
echo $name
函数
系统函数
basename
basename[string/pathname] [suffix]
:basename会删除所有的前缀包括最后一个「“/”」,然后将字符串打印出来。suffix为后缀,如果后缀被指定了,basename会将其去掉
案例
截取/Users/kuma/test.txt
的文件名
basename /Users/kuma/test.txt
basename /Users/kuma/test.txt .txt
dirname
dirname 文件绝对路径
:返回文件路径
案例
获取test.txt的路径
dirname /Users/kuma/test.txt
自定义函数
基本语法
function function_name()
{
fuction主体
}
function_name
经验
- 必须在调用函数的地方之前声明函数,shell是逐行运行。不像其他语言一样先编译
- 函数返回值,只能通过
$?
获得,可以显示的加return
返回。如果不加,将以最后一条命令运行结果作为返回值。return后跟树脂n(0-255)
案例
计算两个输入参数的和
#!/bin/bash
function sum()
{
s=0
s=$[$1+$2]
echo $s
}
read -p "input the num1" num1
read -p "input the num2" num2
sum $num1 $num2
shell工具
cut
基本语法
cut [选项] filename
,默认分割符是制表符
选项参数:
-
-f
:列号,提取第几列 -
-d
:分割符,按照指定分割符分割列
案例
# 准备数据
vim cut.txt
zhang san 1
li si 2
qian wu 3
#切割第1列
cut -d " " -f 1 cut.txt
cat cut.txt | cut -d " " -f 1
#切割第2,3列
cut -d " " -f 2,3 cut.txt
cat cut.txt | cut -d " " -f 2,3
#在文件中切除li
cat cut.txt | grep li | cut -d " " -f 1
# 选取系统path变量值,第2个「:」开始后的所有路径:PATH=「/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/TeX/texbin:/Library/Apple/usr/bin」;result=「/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/TeX/texbin:/Library/Apple/usr/bin」
echo $PATH | cut -d ":" -f 2-
# 切割ifconfig后打印ip
ifconfig eth0 | grep "inet" | cut -d " " -f 2
sed
sed是一种流编辑器,一次处理一行内容。处理的时候,将当前处理行存储在临时缓冲区中,称为“模式空间”。接着用sed处理缓冲区的内容。处理完成后,将处理后的内容送到屏幕。接着处理下一行,这样直到文件末尾,文件内容并没有改变,除非使用重定向存储输出
基本用法
sed [选项] filename
选项参数说明
-e
:直接在指令列模式上进行sed的动作编辑
命令功能描述
-
a
:新增,a的后面可以接字符串,在下一行出现(append) -
d
:删除(delete) -
s
:查找并替换(search)
案例
注意:mac环境下如果报错,那么就需要安装gnu-sed
,然后用gsed
代替sed
brew install gnu-sed
# 创建数据
vim sed.txt
dong shen
guan zhen
wo wo
lai lai
le le
# 在第2行后面新增“this is new”。注意:新增内容在第三行
sed "2a this new" sed.txt
# 删除带有“wo”的行
sed "/wo/ d" sed.txt
# 将「wo」替换成「ni」;「g」代表的是全局替换
sed "s/wo/ni/ g" sed.txt
# 删除第2行,将「wo」替换成你
sed -e "2d" -e "s/wo/ni/g" sed.txt
awk
基本语法
一个强大的文本分析工具,把文件逐行的读入。以空格为默认分割符将每行切片。切开的部分再进行分析处理
基本语法
awk [选项] ‘pattern1{action1} pattern {action2}’ filename
-
pattern
:表示在awk在数据中查找的内容,就是匹配模式 -
action
:在找到匹配内容的时候执行的一列内容
选项参数:
-
-F
:指定输入文件分隔符 -
-v
:赋值一个用户定义变量
案例
# 数据准备
sudo cp /etc/passwd ./
# 搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
awk -F : '/^root/ {print $7}' passwd
# 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。注意:只有匹配了pattern的行才会执行action
awk -F : '/^root/{print $1 "," $7}' passwd
# 只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"yowai,bin/end"。注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
awk -F : 'BEGIN{print "user,shell"} {print $1 "," $7} END{print "yowai,/bin/end"}' passwd
# 将passwd文件中的用户id增加数值1并输出
awk -F : -v i=1 '{print $3+i}' passwd
awk内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数 |
NF | 浏览记录的域的个数(切割后,列的个数) |
# 统计passwd文件名,每行的行号,每行的列数
awk -F : '{print "filename:" FILENAME " " "linenumber:" NR " " "column:" NF}' passwd
# 切割IP
ifconfig vmnet8 | grep "inet" |awk -F " " '{print $2}'
# 查询sed.txt中空行所在的行号
awk '/^$/ {print NR}' sed.txt
sort
sort在linux中非常有用,将文件进行排序,并将结果输出
基本语法
选项 | 说明 |
---|---|
-n |
数值大小 |
-r |
相反的顺序(rverse) |
-t |
设置排序分割字符 |
-k |
指定需要排序的列 |
案例
# 数据准备
vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
# 按照“:”分割后的第三列倒序排序。
sort -t : -nrk 3 sort.sh
面试题
使用命令行查询file中空行所在的行号
awk '/^$/ {print NR}' sed.txt
求和
有文件chengji.txt内容如下:
张三 40
李四 50
王五 60
求第二列的和并输出结果:
cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'
shell中如何查询一个文件是否存在
#!/bin/bash
if [ -f sed.txt ]; then
echo "文件不存在"
else
echo "文件存在"
fi
shell写一个脚本,对文本中无序的一列数字排序
sort -n xinlang.sh | awk '{sum+=$1} {print $1} END{print "sum:"sum}'
查找当前文件夹(/Users/kuma/Desktop/shell)下所有的文本文件内容包含有“shen”的文件名称
grep -r "shen" /Users/kuma/Desktop/shell | cut -d : -f 1
网友评论