(注意:linux中要写shell脚本,必须是.sh的文件,eg: touch tesh.sh ;vim test.sh ; sh test.sh)
Shell是一个命令行表达式,能接受应用程序或用户的命令,然后调用os内核。
Shell脚本固定以#!/bin/bash开头(指定为bash解析器)
bash和sh的关系:sh是bash的一个软链接
eg: name="zhangsan"
注:变量名和等号之间不能有空格。同时,变量名命名要遵循以下规则:
1.命名只能用英文字母、数字、下划线,首字符不能以数字开头
2.变量名之间不能有空格(有空格的话linux会把它当成一个命令),可以有_
3.不能用标点符号
4.不能用bash里的关键字(可用help查看关键字)
readonly 变量名=值
export 变量名
}
echo $ name
echo ${name} 花括号可加,可不加
unset name
注意:echo是个命令,所以需要有空格,只有赋值变量才没有空格
str="hello world!"
str='hello world!'
echo ${#str}
echo ${name:1} 它的意思是选取字符串从第1个到最后一个
echo ${name:0:3}它的意思是选取字符串从0到2
echo ${name:0:100}如果没有100个字符怎么办?最后它会选取到最后一个字符
array=(val1 val2 val3)
array[0]=val1
array[1]=val2
echo ${array[0]}
echo ${array[*]}
echo ${#array[*]}
1.算术运算符
原生bash不支持简单的数学运算,但可以通过其他命令来实现
val=`expr 2 + 2`
val=`expr 2 - 2`
val=`expr 2 / 2`
也可以直接算val=$[2+2]
(注意:表达式和运算符之间要有空格,比如2+2是不对的,要写成 2 + 2 ,完整的表达式要被``包含)
val=`expr 2 \* 2`
val=`$a % $b` (这里a、b是变量)
a=$b (把b的值赋给a)
[ $a == $b ] (相同返回true,不同返回false)
[ $a != $b ](不同返回true,相同返回false)
注意:条件表达式要放在方括号之间,而且必须有空格,
比如:[$a == $b]就是错的,[ $a == $b ]才是对的
2.关系运算符
eg: [ $a -eq $b ]
eg:[ $a -ne $b ]
eg:[ $a -gt $b ]
eg:[ $a -lt $b ]
eg:[ $a -ge $b ]
eg:[ $a -le $b ]
3.布尔运算符
eg:[ ! false ]返回true
eg:[ $ a -lt 20 -o $b -gt 100 ]
eg:[ $ a -lt 20 -a $b -gt 100 ]
4.逻辑运算符
eg:[ $a -lt 100 && $b -gt 100]
eg:[ $a -lt 100 || $b -gt 100]
5.字符串运算符
eg:[ $a = $b ]
eg:[ $a != $b ]
eg:[ -z $a ]
eg:[-n $a ]
eg:[ $a ]
语法:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
第一种:
for ((初始值;循环控制条件;变量变化))
do
command1
.......
done
第二种:
for val in item1 item2 item3 ... itemN
do
command1
....
commandN
done
语法:
while comndition
do
command
done
(这里可能会报错,可能是let的原因,因为/bin/sh指向dash而不是bash,dash不支持let命令
所以,解决办法如下:输入sudo dpkg-reconfigure dash
输入密码
出现个设定dash,选择“否”
)
把输出写入文件: ls -l > ls.txt(删除,覆盖效果)
把输出追加到文件:ls -l >> ls.txt(保留,追加效果)
eg:python test.py >r.txt 2>&1
案例:
重定向正确的输出:head -l /etc/* > result.log
重定向标准错误:head -l /etc/* 2 > error.log
分别重定向标准输出和标准错误:head -l /etc/* >result.log 2>error.log(常用)
选项:
read -p:指定读取值时的提示符
read -t:指定读取值时等待时间(秒)
参数:变量
1.basename [ string / pathname ] [ suffix ]
(basename会删掉所有的前缀,包括最后一个‘/’字符,然后将字符串显示出来)
(如果后缀suffix被指定了,basename会将string/pathname中的suffix去掉)
eg:截取/home/zyy/test.txt路径的文件名称
basename /home/zyy/test.txt
basename /home/zyy/test.txt .txt
2.dirname 文件绝对路径
(从给定的绝对路径中去除文件名(非目录部分),然后返回剩下的路径(目录部分))
eg:获取test.sh的绝对路径
dirname /home/zyy/test.sh
1.基本语法
[ function ] fun_name[()]
{
具体内容
[ return $? ]
}
eg:计算两个输入参数的和
function sum()
{
s=0;
s=$[$1 + $2]
echo $s
}
read -p "输入第一个参数:" p1
read -p "输入第二个参数:" p2
sum $p1 $p2
cut负责在文件中剪切数据,从文件的每行剪切字节、字符、字段,并将这些字节、字符、字段输出
1.基本用法
cut [选项参数] filename
选项参数:-f :列号,提取第几列
-d:分隔符,按照指定分隔符分割列
eg: 切割cut.txt第一列
eg:切割cut.txt第二、三列
eg:在cut文件中切割出“hao”
eg:选取系统PATH变量,第二个:开始后的路径(3-代表第三列及之后所有的)
sed是一种流编辑器,一次处理一行的内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”。然后用sed命令处理缓冲区的内容,处理完成后把缓冲区的内容送往屏幕,接着处理下一行,如此反复。文件内容不会发生改变
1.基本用法
sed [选项参数] 'command' filename
选项参数:-e :多个命令时候加-e
a:新增,a后面能拼接字符串,在下一行出现
d:删除
s:查找并替换
eg:把“hello”这个词插入到sed.txt第二行下(a是插入,2a就是在第二行插入),打印
注意,文件内容不会发生变化
eg:删除sed.txt所有包含hello的行
eg:将sed.txt中的hello替换成world(加g是全局替换,不加只替换第一个)
eg:既把“hello”这个词插入到sed.txt第二行下,又将sed.txt中的hello替换成world
和cut很像,只是处理形式不一样。
把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
1.基本用法
awk [选项参数] ‘pattern1 {action1} pattern2 {action2}...' filename
pattern:表示AWK在数据中查找的内容,就是匹配模式。
action:找到匹配内容时所执行的一系列命令。
选项参数:-F:输入文件的拆分符
-v:赋值一个用户定义变量
操作准备:sudo cp /etc/passwd ./
sudo chown xxx:xxx passwd
eg:搜索passwd文件以root开头的所有文件行(正则匹配),并输出改行的第7列
eg:搜索passwd文件以root关键字开头的所有行,并输出该行第1列和第7列中以“,”分割
eg:只显示/ect/passwd 的第一列和第七列,以逗号分隔,在所有行前面添加列名user,shell。在最后一行添加“zyy, /bin/hello”
eg:将passwd文件中的用户id(在第三列)增加数值1并输出
内置变量
FILENAME:文件名
NR:已读的记录数
NF:切割后列的个数
eg:统计passwd的文件名,每行的行号,每行的列数
eg:查询空行所在的行号(^:匹配字符串开始的位置;$:匹配字符串结尾的位置)
将文件进行排序,并将排序结果标准输出
1.基本语法
sort [选项] [参数]
选项:-n:按照数值大小排列
-r:倒序排列
-t:设置排序时的分隔字符
-k:指定需要排序的列
数据准备:
eg:按照:分隔后的第2列倒叙排序
面试题:
1.使用linux查询file1中空行所在的行号
awk '/^$/ {print NR} ' file1
2.有文件file1内容如下:
张三 40
李四 60
王五 99
用Linux命令计算第二列的和并输出。
cat file1 | awk -F " " -v sum=0 '{ sum+=$2 } END {print sum} '
3.shell检查一个文件是否存在
4.用shell对文本中无序的一列数字排序
5.用shell查找当前文件夹/home下的所有文本内容中包含“hello”的文件名称