3

吴宏东 - 记于2018年07月03日 - 博客 https://segmentfault.com/u/wu...

Linux Shell 基础语法

脚本

标记

#!/bin/bash是shell脚本的第一行代码,表示该脚本使用什么解释器;

#!/bin/bash

echo命令用于向窗口输出文本;

echo "hello shell";
# 开启转义 换行
echo -e "hello \n shell";
# 反引号 显示命令执行结果
echo `ls /`;
# 将显示结果定向到文件
echo 'hello' > 1.txt;

单行注释

# 表示单行注释;

多行注释,EOF还可以用其他符号,例如!

:>>EOF  
注释内容1 
注释内容2
EOF

:>>!
注释内容1 
注释内容2
!

例子

创建脚本文件,命名为/tmp/hello.sh

#!/bin/bash
echo "hello shell";

赋予脚本执行的权限,执行脚本

chmod u+x /tmp/hello.sh;
./tmp/hello.sh

变量

定义使用

格式:key=value;
value当为单引号或双引号内容时,即为字符串;当为数字时,即为数值型;
使用变量用美元符号$引用,标准格式是:${key};但有时也可以使用$key;进行引用;

# 字符串变量
a='A';
b="${a}\\B";
# 只读变量
readonly c=7;
# 全局变量
export d=3.14;
# 单引号的内容会原样输出,不能出现单引号,不能使用转义字符
echo $a;
# 双引号内容可以包含变量,可以使用转义字符
echo $b;
# 删除变量
unset c;

字符串

n="0123456789";
m="aaabbbaaabbb";
# 返回字符串变量n的长度
echo ${#n};
# 返回从第5个字符开始到最后的部分
echo ${n:5};
# 返回从第0个字符开始,长度为5的部分
echo ${n:0:5};
# 删除开头部分与012匹配的部分
echo ${n#012};
# 删除结尾部分与789匹配的部分
echo ${n%789};
# 替换第一次出现的aaa为xxx
echo ${m/aaa/xxx};
# 替换全部aaa为xxx
echo ${m//aaa/xxx};
# 替换开头部分的aaa为xxx
echo ${m/#aaa/xxx};
# 替换结尾部分的bbb为xxx
echo ${m/%aaa/xxx};

执行输出:

10
56789
01234
3456789
0123456
xxxbbbaaabbb
xxxbbbxxxbbb
xxxbbbaaabbb
aaabbbaaabbb

替换扩展

v=V;
echo $v;
# 若v未定义或为空值,则返回vvv,但v的值不变;若v存在且非空,则返回V;
echo ${v:-vvv};
# 若v未定义或为空值,则返回vvv,且v的值被赋值为vvv;若v存在且非空,则返回V;
echo ${v:=vvv};
# 若v未定义或为空值,则返回vvv,并终止脚本;若v存在且非空,则返回V;
echo ${v:?vvv};
# 若v未定义或为空值,则返回空值,但v的值不变;若v存在且非空,则返回vvv;
echo ${v:+vvv};

数值运算

四则运算符:+、-、*、/
幂运算符、模运算符:**、%
自增自减运算符:++、--
赋值运算符:=、+=、-=、*=、/=、%=
比较运算符:<、>、<=、>=、==、!=
逻辑运算符:&&、||、!

# 运算表达式必须在双括号内((表达式))
echo $((a=3**2));# 输出9

变量输入

格式:read -p <Prompt String> [<变量名>...];

# 输入单个变量
read -p "请输入:" n;
echo $n;
# 输入多个变量
read -p "请输入:" n1 n2 n3;
echo $n1 / $n2 / $n3;

返回值

每个命令都会返回一个状态码,0表示成功,其他非零数值表示各种情况的错误,exit n;(n的范围是0~255),1表示通用错误,126表示没有执行权限,127表示命令没有找到;

参数

传参

格式:./shell脚本文件 参数1 参数2 ...

# 向脚本文件test.sh参入3个参数
./shell/test.sh p1 p2 p3;
# test.sh文件内获取参数
echo $1 $2 $3;

获参

# 传递到脚本的参数个数
echo $#;
# 显示所有参数
echo $*;
echo $@;
# 显示第1个参数
echo $1;
# 显示第10个参数,第10个参数起必须使用${n}
echo ${10};
# 显示最后命令的退出状态,0表示没有错误,其他值表示有错;
echo $?;
# 当前进程的PID
echo $$;

测试表达式

测试语句

格式1:test <测试表达式>
格式2:[ <测试表达式> ]
格式3:[[ <测试表达式> ]]
格式1和格式2等价,格式3可以使用&&、||、!的逻辑连接符;
格式2和3符号前后必须留空格;

a=1.1;
b=1.1;
if test $a == $b; then
# if (( $a == $b )); then
# if [ $a -eq $b ]; then
# if [[ $a == $b ]]; then
echo '相等';
fi;

字符串测试

-z str 字符串是否为空串;
-n str 字符串是否为非空串;
str1 == str2 两个字符串是否相同;
str1 != str2 两个字符串是否不同;

整数二元比较

[] 中使用-eq、-ne、-gt、-ge、-lt、-le;
(())中使用==、!=、>、>=、<、<=;
[]中使用-a、-o、!;
[[]]中使用&&、||、!;

文件目录测试

-e file 文件是否存在;
-f file 是否普通文件;
-d file 是否目录;
-L file 是否链接文件;
-b file 是否为块设备文件;
-c file 是否为字符设备文件;
-s file 是否长度不为零、非空文件;
-r file 是否为可读文件;
-w file 是否为可写文件;
-x file 是否为可执行文件;
-O file 是否为文件的属主;
-G file 是否为文件的属组;
-u file 是否设置了SUID的权限;
-g file 是否设置了SGID的权限;

# 当目录不存在时创建该目录
[ !-e /shell ] && mkdir -p /shell;

数组

定义

格式1:array=(a1 'a2' a3);
格式2:array[0]=a1;array[1]='a2';array[2]=a3;

# 定义数组
array=(1 '2');
# 设置第三个元素
array[2]=3;
# 显示第一个元素
echo array[0];
# 获取数组的全部元素
echo ${array[*]};
echo ${array[@]};
# 获取数组的大小
echo ${#array[*]};

函数

定义

格式:function fun() { }
function关键字可以省略;
可以添加返回 return n;(n必须是0~255)执行函数后,可以通过$?获取返回值;

fun() {
    return 1;
    echo 'over';
}
fun;
echo $?;

流程控制

if 语句

if test -e /shell/1; then
    echo '1文件存在';
elif test -e /shell/2; then
    echo '2文件存在';
# else分支是最后的默认分支,可以省略,最多只能一个
else 
    echo '都不存在';
fi;

case 语句

read -p '请输入:' num;
case $num in
1) echo 'num=1' ;;
2) echo 'num=2' ;;
*) echo 'num=?' ;;
esac

while 语句

break:跳出循环;
continue:跳过本次循环,进入下一次迭代;
exit n:会中止当前函数以及调用它的主shell;

i=0;
len=10;
while (($i < $len));do
    echo $i;
    let "i++";
done;
# 循环读取文件行内容
while read line;
do
    echo $line;
done < /shell/proxy;
# 或
cat /shell/proxy | while read line;
do
    echo $line;
done;

until 语句

until 表达式与while相反,当返回值为0时结束循环;

for 语句

# 字面常量列表
for loop in 1 2 3 4 5;
do
    echo "The value is: $loop"
done;
# 参数列表,in $@可以省略
for p in $@;
do
    echo $p;
done;
# 序列列表
for x in {1..9};
do
    echo $x;
done;
# C语言型for循环
for((i=0;i<10;i++)) {
    echo $i;
}

select 语句

select是一种菜单循环结构,无限循环,退出可以加入break或按<Ctrl+C>,一般加入case语句处理;

select x in 1 2 3;
do
    case $x in 
    1) echo 'x=1' ;;
    *) echo 'x=?' ;; 
    esac;
done;

无限循环

while :
# 或 while true
do
    echo 'loop';
done;
for(( ; ; )){
    echo 'loop';
}

吴宏东
25 声望4 粉丝

专注于Linux系统信息安全,精通渗透测试、安全审计、漏洞分析、反入侵技术。