#! /bin/bash
上面是用 /bin/bash 来解析脚本 也可以用 /bin/sh 来解析的
比如我们C的printf 在shell 可以用 echo 来输出。
下面是输出 hello world 这个字符串
#! /bin/bash
echo "hello world" #输出 hello world 字符串
也可以直接在你的终端执行 echo "hello world" 一样的效果 如下图

# 第一种 最常用
./xx.sh #这种你需要 给它一个可执行权限
#命令: chmod +x xx.sh 才可以执行.
# 第二种
bash xx.sh
# 第三种
sh xx.sh
也可以看下方我在终端执行的命令

指令:
首先我这里建立一个文件 叫 xx 里面内容为空
touch xx
然后我通过echo 方式 写 hello world 到 xx文件中。(不先创建 xx也是可以的,如果你没有xx文件,下面指令也会给你创建的)
echo "hello world" > xx
> 是会将内容覆盖的 就是会原来有数据 将会被清空, 再写入内容
如图所示:

如果不想覆盖原来的 在后面增加进去,则可以用下方的这个
指令:
把 hello world 追加到 xx 文件
echo "hello world" >> xx
>> 是追加的方式写入文件 原有的内容保留,再末尾添加内容

首先得知道下面的几种符号的含义。
$n
n:为数字 $0代表该脚本的名称 $1~$9代表第一到第九个参数,十以上的参数需要用大括号包含如 ${10}
$#
获取所有输入参数的个数 常用于循环 判断参数的个数是否正确以及加强脚本的健壮性。
$*
这个变量代表命令行中的所有参数 $*把所有的参数看成一个整体
$@
这个变量也代表命令行中的所有参数 不过$@把每一个参数区分对待
$?
最后一次执行的命令的返回状态,如果这个变量的值为0 证明上一个命令正确执行,如果这个变量的值
为非0 (具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了
变量的定义 (变量没有类型的,所以直接写就行了)
简单的代码实例
#! /bin/bash
num=10
string="hello world"
echo $num #输出 num 的值
echo $string #输出 string 的值
运行结果:

环境变量
下面的操作只能在同一个终端才有效。
XX 为 100 的这么个环境变量export XX=100
export
XXunset XX
echo $XX
~/.profile 文件中去.~/.profile 文件中去echo "export AA=100" >> ~/.profile
执行这个指令 让上面这行 生效
source ~/.profile
输出环境变量值
echo $XX
/etc/profile 里面去把这个 export AA=100 输出到 /etc/profile 里面去
echo "export AA=100" >> /etc/profile
执行这个文件 让我们指令生效
source /etc/profile
输出环境变量值
echo $AA
#! /bin/bash
################################# 常用数组 #################################
array1=(1 2 3 4 5)
array2=('1' '2' '3' '4' '5')
array3=("111" "222" "333" "444" "555")
echo ${array1[0]} #输出第0个元素
echo ${array2[1]} #输出第0个元素
echo ${array3[2]} #输出第0个元素
echo ${array3[@]} #输出所有元素
echo ${#array3[@]} #输出元素个数
echo ${!array3[@]} #输出所有下标
echo ${array3[@]:1} #输出从下标为1开始输出
echo ${array3[@]:1:2} #输出从下标为1开始输出 到 下标为2结束
################################# 关联数组 #################################
#定义方式
declare -A array4
declare -A array5
#单个赋值
array4[num]=4
array4[name]="pipi"
array4[score]=60
#全部赋值
array5=([num]=5 [name]="keke" [score]=50)
#输出信息
echo ${array4[@]}
echo ${array5[@]}
这个就相当于我们 main函数的参数 int main(int argc,char **argv) 运行的时候 就带上参数。
这里先说一下 $n
n:为数字 $0代表该脚本的名称 $1~$9代表第一到第九个参数,十以上的参数需要用大括号包含如 ${10}
我们还是直接写个小示例
#! /bin/bash
name=$1
echo "hello $name"
echo "参数个数为 $#"
echo "所有参数为 $*"
执行结果:

#! /bin/bash
# 方式1
# 注意: 用下方let 方式计算 不能有空格不能如 num=num + 100 这是错误写法
num=100
# 加法
let num=num+100
# 减法
let num=num-100
# 乘法
let num=num*100
# 除法
let num=num/100
echo $num
#! /bin/bash
# 方式2
# 注意: 下方写法表达式内可以用空格隔开 如 num=$[ num + 100 ] 这是可以的
num=100
# 加法
num=$[num+100] 或 num=$[ num + 100 ]
# 减法
num=$[num-100] 或 num=$[ num - 100 ]
# 乘法
num=$[num*100] 或 num=$[ num * 100 ]
# 除法
num=$[num/100] 或 num=$[ num / 100 ]
echo $num
#! /bin/bash
# 方式3
# 注意: 下方写法表达式内可以用空格隔开 如 num=$(( num + 100 )) 这是可以的
num=100
# 加法
num=$((num+100)) 或 num=$(( num + 100 ))
# 减法
num=$((num-100)) 或 num=$(( num - 100 ))
# 乘法
num=$((num*100)) 或 num=$(( num * 100 ))
# 除法
num=$((num/100)) 或 num=$(( num / 100 ))
echo $num
#! /bin/bash
# 方式4
# 注意: 下方表达式必须 空格 隔开 !!!
num=100
# 加法
num=`expr $num + 100`
# 减法
num=`expr $num - 100`
# 乘法
num=`expr $num \* 100` # *符号前面请加 \
# 除法
num=`expr $num / 100`
echo $num
以上就是不同方式进行 数学运算的方法了,我个人还是觉得用 方式3 好点。
示例代码:
用表中符号来判断 想了解判断符号可在终端输入命令 man 1 test 来查看.
| 符号 | 等价于C语言的符号 |
|---|---|
| -eq | == |
| -ne | != |
| -gt | > |
| -lt | < |
| -ge | >= |
| -le | <= |
示例:
#!/bin/bash
num=$1 #获取一个命令行参数
######################## 方式1 ########################
if [ $num -eq 100 ]
then
echo "等于100"
elif [ $num -gt 100 ]
then
echo "大于100"
else
echo "小于100"
fi
# 或者也可以加上双引号 如下
if [ "$num" -eq "100" ]
then
echo "等于100"
elif [ "$num" -gt "100" ]
then
echo "大于100"
else
echo "小于100"
fi
也可以不用上面表中符号,直接用 >、>=、 等符号 但是请用 (()) 来写。
示例
#!/bin/bash
######################## 方式2 ########################
if (( $num == 100 ))
then
echo "等于100"
elif (( $num >= 100 ))
then
echo "大于100"
else
echo "小于100"
fi
# 或者也可以加上双引号 如下
if (( "$num" == "100" ))
then
echo "等于100"
elif (( "$num" >= "100" ))
then
echo "大于100"
else
echo "小于100"
fi
[]的表示方式 其中用 = 和 == 都是可以的
#! /bin/bash
string1="hello"
string2="hello"
if [ $string1 = $string2 ]
then
echo "字符串一样"
else
echo "字符串不一样"
fi
# 也可以加上双引号 如下方
#! /bin/bash
string1="hello"
string2="hello"
if [ "$string1" = "$string2" ]
then
echo "字符串一样"
else
echo "字符串不一样"
fi
[[]] 的表示方式 其中用 = 和 == 都是可以的
#! /bin/bash
string1="hello"
string2="hello"
if [[ $string1 == $string2 ]]
then
echo "字符串一样"
else
echo "字符串不一样"
fi
# 也可以加上双引号 如下方
#! /bin/bash
string1="hello"
string2="hello"
if [[ "$string1" == "$string2" ]]
then
echo "字符串一样"
else
echo "字符串不一样"
fi
示例代码:
)相当于C语言的case中的:。 ;;相当于C语言的 break;
#! /bin/bash
# 获取键盘上值 (相当于C语言的 scanf)
read num
case $num in
[a-z])
echo "小写字母"
;;
[A-Z])
echo "大写字母"
;;
[0-9])
echo "数字"
;;
*)
echo "其它"
;;
esac
示例代码:
#! /bin/bash
# 循环3次 分别 i 的值是 0、1、2
for ((i=0;i<3;i++))
do
touch $i
echo "hello $i" > $i
done
# 也可以用空格隔开如下
for (( i=0; i<3; i++ ))
do
echo $i
done
# 也可以用空格隔开如下
for (( i = 0; i < 3; i++ ))
do
echo $i
done
# 一般比较多的是我们去 遍历数组里面的元素 把每一个元素打印出来
#! /bin/bash
# 数组的定义
array=( "111" "222" "333" )
# 遍历每一个元素,并输出
for (( i = 0; i < ${#array3[@]}; i++ ))
do
echo "$i"
done
# ${#array3[@]} 就是指数组元素个数
# 输出结果:
111
222
333
#! /bin/bash
# 循环3次 分别 i 的值是 0、1、2
for i in {0..2}
do
echo $i
done
# 在shell中是没有类型这说法的,所以for循环字符串也是可以的。
# 数组的定义
array=( "111" "222" "333" )
# 遍历每一个元素,并输出
for i in ${array[@]}
do
echo $i
done
# ${array[@]} 是指所有元素
# 输出结果:
111
222
333
# 循环3次 分别 i 的值是 0、1、2
for i in 0 1 2
do
echo $i
done
# 可以随意写 字符串也可以的
# 循环3次 分别 i 的值是 1、100、1000
for i in 1 100 1000
do
echo $i
done
# 也可以这样
# 循环3次 分别 i 的值是 111、222、333
for i in "111" "222" "333"
do
echo $i
done
#!/bin/bash
# 死循环
while :
do
# 在这里添加要执行的代码
done
# 不断获取键盘值 并且输出 read 就相当于 C语言的 scanf()
while read i
do
echo $i
done
# 不断从xx.txt文件中读取内容 并且输出
while read i
do
echo $i
done < xx.txt
正则表达式
通常被用来检索/替换那些符合某个模式的文本,在linux中
grep, sed, awk 等文本处理工具都支持通过正则表达式进行模式匹配。下面表中符号切记记住,因为经常会用来结合 三剑客的。
| 符号 | 描述 |
|---|---|
| ^ | 匹配行首,比如 ^hello 就是匹配以 hello 开头的行 |
| $ | 匹配结尾,比如 hello$ 就是匹配以 hello 结尾的行 |
| . | 匹配任意一个字符(除了换行符) |
| * | 前一个字符匹配0次或任意多次 |
| [] | 匹配中括号里面指定的任意一个字符,只匹配一个字符, 例如 [abc] 表示匹配a、b、c 这三个任意一个字符。[a-z] 表示匹配是小写字母,[0-9] 表示匹配是数字0~9。 |
| [^] | 匹配除了中括号的字符之外的任意一个字符,跟上述是相反的。例如 [^abc] 匹配的是除了a,b,c的其他任意字符。[^0-9] 表示匹配除了数字的任意字符。 |
grep 是一个文件过滤工具。
grep [options] [pattern] file
作用:文本搜索工具,过滤 条件
| 选项参数 | 描述 |
|---|---|
| -i | ignorecase 忽略字符大小写 |
| -o | 仅显示匹配到的字符串本身 |
| -v | 显示不能被模式匹配的行 |
| -E | 支持用扩展的正则表达式 |
| -q | 静默模式,即不输出任何信息 |
| -n | 显示行号 |
| -c | 只统计匹配行数 |
| -w | 只匹配过滤的单词 |
| –color=auto | 使用grep过滤结果添加颜色 |
常规匹配
一串不包含特殊字符的正则表达式 匹配它自己,例如
aa.c 文件 中 找 字符串 abccat aa.c | grep adc
aa.c 文件中 以 abc 开头的字符串cat aa.c | grep ^abc
aa.c 文件中 以 abc 结尾的字符串cat aa.c | grep abc$
aa.c 文件中 以 abc 开头 并且 以 abc 结尾 的字符串cat aa.c | grep ^abcabc$ (这样写法只有 abcabc 才能匹配上)
aa.c 文件中 空行cat aa.c | grep ^$
显示行号 请加上 -ncat aa.c | grep -n ^$
aa.c 文件中 以 i 开头, 中间两个任意字符(包括特殊符号), f 结尾的 字符串cat aa.c | grep i..f
.
*cat aa.c | grep ro*t
cat aa.c | grep .*
aa.c 文件中 以 i 开头 以 f 结尾cat aa.c | grep ^i.*f$
aa.c 文件中 以 i 开头 中间随意 然后 出现 in 然后中间随意 f 结尾的字符串cat aa.c | grep ^i.*in.*f$
字符区间[]
aa.c 文件中 出现 i开始 中间是字符a-z 不限个数 fcat aa.c | grep i[a-z]*f
aa.c 文件中 出现 $字符的字符串 需要转义cat aa.c | grep '\$'
grep 也可以配合 选项参数 来进一步获取想要的内容。我这里就不写那么多了。
awk 是一个强大的文本分析工具,把文件逐行的读入,以空格为默认分割符将每行切片,切开
的部分再进行分析处理。
awk [option] 'pattern[action]' file...pattern:
action:
file
awk 可选参数 模式 '条件动作' 文件
默认是空格作为空格符,且多个空格也识别成为一个空格 作为分隔符
awk是按行处理文件 一行处理完毕 处理下一行 …
自定义输出,必须外层单引号,内层双引号。
-F 指定分隔符-v 定义或修改一个awk内部的变量-f 从脚本文件中读取awk命令下面是 awk 特殊的内置变量, 这里只是列举了我常用的,更多命令 可通过 命令 man awk 查看
| 选项参数 | 描述 |
|---|---|
| $0 | 所有内容 |
| $n | 第n列。例如 $1 就是第 1 列,$10 就是第 10 列 |
| $NF | 最后一列 |
| $(NF-n) | 倒数第n列。例如 倒数第二列则是 $(NF-1) |
| NR | 行数。 例如 NR==1 就是第一行 |
| FILENAME | 文件名 |
如果不懂第几列 行的概念,我这里就举例一下。
比如我有一个文件叫 xx ,内容如下
AAA BBB CCC DDD EEE
111 222 333 444 555
!!! === --- *** +++
1 22 333 444 555

是不是很容易理解,awk 是 按空格 来分割的,按行处理的。
再来一个 示例 free -m 列出内容如下图,记得是按 空格 分割的。下面同颜色框起来的为同一列

下面就开始列举一些示例
xx 文件中全部内容, $0 表示所有内容awk '{print $0}' xx
xx 文件中第一列内容, $1 表示第一列 (第列 就 $n)awk '{print $1}' xx
xx 文件中 最后一列内容, $NF 表示最后一列awk '{print $NF}' xx
xx 文件中 第一列和第二列内容 并且空格隔开。awk '{print $1,$2}' xx
xx 文件中第一行所有内容, NR==1 表示第一行,$0 表示 所有内容。(第n行 就 NR==n)awk 'NR==1 {print $0}' xx
xx 文件中第一行,第二行所有内容。awk 'NR==1,NR==2 {print $0}' xx
或
awk 'NR==1 || NR==2 {print $0}' xx
xx 文件中 第一行到第三行的所有内容awk '(NR>=1)&&(NR<=3){print}' xx
xx 文件中 奇数 行 所有内容awk '(NR%2)==1 {print $0}' xx
xx 文件中 偶数 行 所有内容awk '(NR%2)==0 {print $0}' xx
xx 文件中 第一行 第一列 内容awk 'NR==1 {print $1}' xx
指定符号分割操作
xx 文件中 按 : 符号 进行分割,第一列内容。 指定符号分割 加上 -F "符号" 即可awk -F ":" '{print $1}' xx
这个还是比较简单,这里就不多演示了。
寻找文件中是否 有需要找的 字符串
xx 文件中 有AAA字符串的 行内容awk '/AAA/ {print $0}' xx
xx 文件中 第二行 第一列中的 111 +1 变成 112. (注意: +1操作不会影响文件中本身的值,还是保持 111)方式1 直接 +1
awk 'NR==2 {print $1+1}' xx
方式2 可以通过-v 引入变量 实现运算
awk -v i=1 'NR==2 {print $1+i}' xx
xx 文件中所有内容,并且在每一行后面加上 " XXX" (这里只是输出,并不是会在原文件添加 " XXX")awk '{print $0 " XXX"}' xx
xx 文件中 第一行 内容,并且在输出第一行内容前 输出 "hello" 在输出第一行内容后 输出 "world"。BEGIN: 在所有数据读取行之前执行END: 在所有数据执行后执行awk 'BEGIN{print "hello"} NR==1{print $0} END{print "world"}' xx
输出结果如下:
hello
AAA BBB CCC DDD EEE
world
xx 文件中当前文件名 并且输出第一行的内容,并且空格隔开。awk 'NR==1 {print FILENAME,$1}' xx
ifconfig | awk '/netmask/ {print $2}'
结果如下:
192.168.1.101
127.0.0.1
sed 用法
sed [项目] [sed内置命令字符] [输入文件]
下面表的内容只是一部分。
| 选项参数 | 描述 |
|---|---|
| -n | 取消默认sed的输出 常与sed内置命令p一起用 |
| -i | 直接将修改结果写入文件 不用-i sed修改的是内存数据 |
| -e | 多次编辑 不需要管道符了 |
| -r | 支持正则扩展 |
下面是 sed 的 内置命令
| 内置命令 | 描述 |
|---|---|
| a | append 对文本追加 在指定后面添加一行/多行文本 |
| d | Delete 删除匹配行 |
| i | insert 表示插入文本,在指定行前添加一行/多行文本 |
| p | print 打印匹配行的内容 通过p与-n 一起用 |
| c | 替换指定的整行内容 |
下面写一些操作示例。
获取文件内容
xx 文件中 第一行内容 (请加上 -n 不然是所有内容都输出的. 想输出第n行就改成 'np' )sed -n '1p' xx
xx 文件中 所有内容sed -n 'p' xx
xx 文件中 第一行到第三行 内容sed -n '1,3p' xx
xx 文件中 最后一行 内容sed -n '$p' xx
给文件添加内容
如果想要将修改结果写入文件 请一定要在sed 后面 加上 -i
如果想要将修改结果写入文件 请一定要在sed 后面 加上 -i
如果想要将修改结果写入文件 请一定要在sed 后面 加上 -i
不加 -i 是不会真正修改的,只是输出给你看而已。(调试建议还是先不加,免得乱改文件内容)
我下面是没有加 -i 的,所以下面的命令不会对文件进行修改。下面的''也可以用 ""代替。
在指定行上面添加内容
xx 文件 第一行的上面插入 “hello world” (ni+要插入的内容,其中n代表行号)sed '1ihello world' xx
xx 文件 最后的行上面插入 “hello world” 到文件末尾 ($i+要插入内容)sed '$ihello world' xx
xx 文件 每一行的上面插入 “hello world” (i+要插入的内容)sed 'ihello world' xx
在指定行下面添加内容
xx 文件 第一行的下面插入 “hello world” (na+要插入的内容,其中n代表行号)sed '1ahello world' xx
xx 文件 最后的行下面插入 “hello world” 到文件末尾 ($a+要插入内容)sed '$ahello world' xx
xx 文件 每一行的下面插入 “hello world” (a+要插入的内容)sed 'ahello world' xx
指定字符行添加内容
xx 文件 凡是以 “AAA” 开头的,在该行的上面插入 “hello world”sed '/^AAA/ihello world' xx
xx 文件 凡是以 “AAA” 开头的,在该行的下面插入 “hello world”sed '/^AAA/ahello world' xx
替换指定的整行内容
xx 文件中 把第一行内容 换成 “hello world” (第1行就 1c ,第n行 则是 nc)sed '1chello world' xx
xx 文件中 把所有行内容 换成 “hello world”sed 'chello world' xx
xx 文件中 把 “AAA” 开头的行 都换成 “hello world”sed '/^AAA/chello world' xx
替换指定的字符
语法格式:
sed "s/需要替换的内容/新的内容/g" 文件名
s :替换指定字符
g :全局的意思
xx 文件中 AAA 改成 666. 不加 g 则替换一个, 加上 g 则是全局替换sed 's/AAA/666/g' xx
删除指定的整行内容
xx 文件中 删除第一行内容 (想删除第一行就 1d 第n行就 nd)sed '1d' xx
xx 文件中 删除最后一行内容sed '$d' xx
xx 文件中 删除第一行到第三行内容sed '1,3d' xx
文本处理工具
cut的工作就是"剪" 具体的说就是在文件中负责剪切数据用的,cut命令从文件的每一行剪切字节,字符和字段并将这些字节,字符和字段输出。
cut [选项参数] filename
说明 默认分割符是制表符
| 选项参数 | 描述 |
|---|---|
| -f | 列号 提取第几列 |
| -d | 分割符 按照指定分割符分割列 默认是制表符 “\t” |
| -c | 按字符进行切割 后加加n 表示取第几列 比如 -c 1 |
还是用这个 xx 文件内容来举例把
xx 文件内容如下
AAA BBB CCC DDD EEE
111 222 333 444 555
!!! === --- *** +++
1 22 333 444 555
xx 文件中 以一个空格 进行裁剪 输出第一列内容 (-d 指定分割符号 -f 指定获取第几列)cut -d " " -f 1 xx
输出内容如下:
AAA
111
!!!
结果看出来了吧,cut 和 awk 是不一样的。
xx 文件中 第一列到第三列 内容 以一个空格进行裁剪cut -d " " -f 1-3 xx
输出结果如下:
AAA BBB CCC
111 222 333
!!! === ---
1
xx 文件中 第二列开始往后所有 内容 以一个空格进行裁剪cut -d " " -f 2- xx
输出结果如下:
BBB CCC DDD EEE
222 333 444 555
=== --- *** +++
1 22 333 444 555
shell 命令很多,我这里也是写了一些我用到的,还有很多内容我都没写,以后看用到了别的再添加进来把,个人觉得,如果是找 关键词 可以先用 grep 来获取,awk 我是对 获取列内容会优先选择它, sed 一般是对文件内容进行替换等操作我会用它。总之,只要你做出来,怎么结合都可以啦 hh。
继续加油!
如果觉得写得可以的,给我点赞评论就更好啦。如果有错也望指出。