面试 SHELL脚本开发

SHELL脚本开发

流程控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash
# ods层数据库和表初始化脚本,只需要执行一次

hive -e "
create database if not exists ods_mall;

create external table if not exists ods_mall.ods_user_active(
log string
)partitioned by (dt string)
row format delimited
fields terminated by '\t'
location 'hdfs://bigdata01:9000/data/ods/user_action/';


create external table if not exists ods_mall.ods_click_good(
log string
)partitioned by (dt string)
row format delimited
fields terminated by '\t'
location 'hdfs://bigdata01:9000/data/ods/user_action/';


create external table if not exists ods_mall.ods_good_item(
log string
)partitioned by (dt string)
row format delimited
fields terminated by '\t'
location 'hdfs://bigdata01:9000/data/ods/user_action/';


create external table if not exists ods_mall.ods_good_list(
log string
)partitioned by (dt string)
row format delimited
fields terminated by '\t'
location 'hdfs://bigdata01:9000/data/ods/user_action/';


create external table if not exists ods_mall.ods_app_close(
log string
)partitioned by (dt string)
row format delimited
fields terminated by '\t'
location 'hdfs://bigdata01:9000/data/ods/user_action/';

"

if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# 给外部分区表添加分区
# 接收三个参数
#1:表名
#2:分区字段dt的值:格式20260101
#3:分区路径(相对路径或者绝对路径都可以)

if [ $# != 3 ]
then
echo "参数异常:add_partition.sh <tabkle_name> <dt> <path>"
exit 100
fi

table_name=$1
dt=$2
path=$3

hive -e "
alter table ${table_name} add if not exists partition(dt='${dt}') location '${path}';
"

for

1
2
3
4
for file in `ls /etc`

for file in $(ls /etc)
以上语句将 /etc 下目录的文件名循环出来。

变量

1
2
3
定义变量时,变量名不加美元符号($,PHP语言中变量需要),如:

your_name="runoob"

使用变量

1
2
3
4
5
6
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

实例
your_name="qinjx"
echo $your_name
echo ${your_name}
1
2
3
4
5
6
7
8
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

实例
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done

如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

只读变量

1
2
3
4
#!/bin/bash

myUrl="https://www.google.com"
readonly myUrl

删除变量

1
2
3
4
使用 unset 命令可以删除变量。语法:

unset variable_name
变量被删除后不能再次使用。unset 命令不能删除只读变量。
1
2
3
4
5
6
#!/bin/sh

myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
以上实例执行将没有任何输出。

变量类型

字符串变量

1
2
3
4
5
6
在 Shell中,变量通常被视为字符串。
你可以使用单引号 ' 或双引号 " 来定义字符串,例如:

my_string='Hello, World!'
或者
my_string="Hello, World!"

整数变量

1
2
3
4
5
6
 在一些Shell中,你可以使用 declare 或 typeset 命令来声明整数变量。

这样的变量只包含整数值,例如:

declare -i my_integer=42
这样的声明告诉 Shell 将 my_integer 视为整数,如果尝试将非整数值赋给它,Shell会尝试将其转换为整数。

数组变量

1
2
3
4
5
6
7
8
9
10
 Shell 也支持数组,允许你在一个变量中存储多个值。

数组可以是整数索引数组或关联数组,以下是一个简单的整数索引数组的例子:

my_array=(1 2 3 4 5)
或者关联数组:

declare -A associative_array
associative_array["name"]="John"
associative_array["age"]=30

环境变量

1
2
3
4
5
这些是由操作系统或用户设置的特殊变量,用于配置 Shell 的行为和影响其执行环境。

例如,PATH 变量包含了操作系统搜索可执行文件的路径:

echo $PATH

特殊变量

1
2
3
有一些特殊变量在 Shell 中具有特殊含义,例如 $0 表示脚本的名称,$1, $2, 等表示脚本的参数。

$#表示传递给脚本的参数数量,$? 表示上一个命令的退出状态等。

字符串

1
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。

单引号

1
2
3
4
5
str='this is a string'
单引号字符串的限制:

单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字符串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号

1
2
3
4
5
6
7
8
9
10
your_name="runoob"
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str
输出结果为:

Hello, I know you are "runoob"!
双引号的优点:

双引号里可以有变量
双引号里可以出现转义字符

拼接字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3


输出结果为:
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !

获取字符串长度

1
2
3
4
5
6
7
string="abcd"
echo ${#string} # 输出 4
变量为字符串时,${#string} 等价于 ${#string[0]}:

实例
string="abcd"
echo ${#string[0]} # 输出 4

提取子字符串

1
2
3
4
5
6
以下实例从字符串第 2 个字符开始截取 4 个字符:

实例
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
注意:第一个字符的索引值为 0。

查找子字符串

1
2
3
4
5
6
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

实例
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 ... 值n)
例如:

array_name=(value0 value1 value2 value3)
或者

array_name=(
value0
value1
value2
value3
)
还可以单独定义数组的各个分量:

array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
可以不使用连续的下标,而且下标的范围没有限制。

读取数组

1
2
3
4
5
6
7
8
9
读取数组元素值的一般格式是:

${数组名[下标]}
例如:

valuen=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:

echo ${array_name[@]}

获取数组的长度

1
2
3
4
5
6
7
8
9
获取数组长度的方法与获取字符串长度的方法相同,例如:

实例
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}

注释

单行注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
以 # 开头的行就是注释,会被解释器忽略。

通过每一行加一个 # 号设置多行注释,像这样:

实例
#--------------------------------------------
# 这是一个注释
# author:菜鸟教程
# site:www.runoob.com
# slogan:学的不仅是技术,更是梦想!
#--------------------------------------------
##### 用户配置区 开始 #####
#
#
# 这里可以添加脚本描述信息
#
#
##### 用户配置区 结束 #####
如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,怎么办呢?

每一行加个#符号太费力了,可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。

多行注释

传递参数