shell脚本编程 4

Shell脚本编程4

一、杂项知识整理

1、数组赋值方法:

declare -a files

files=(/var/log/*.log)通配所有文件也可

2、创建临时文件:

mktemp命令:创建的临时文件可避免冲突

mktemp  NAME.XXXX(x至少要出现三个)

-d 创建临时目录

–tmpdir=/DIR 指明临时文件所存放的目录位置

[root@localhost tmp.X2wtb]# mktemp -d /testdir/tmp.XXXXX
/testdir/tmp.yHrX9
[root@localhost tmp.X2wtb]# ll /testdir/tmp.*
/testdir/tmp.X2wtb:
总用量 0
/testdir/tmp.yHrX9:
总用量 0

3、install命令:安装复制文件:

-m  MODE 指定权限,默认为755

-o  OWNER 指定所有者

-g  GROUP 指定所属组

[root@localhost testdir]# install -m 770 -o root -g root -d tmpinstall
[root@localhost testdir]# ll tmpinstall/
总用量 0
[root@localhost testdir]# ll tmpinstall
总用量 0
[root@localhost testdir]# ll -d  tmpinstall
drwxrwx--- 2 root root 4096 8月  23 17:40 tmpinstall

4、bash如何展开命令行:

把命令行分成单个命令词

展开别名

展开大括号中的声明

展开波浪符声明

命令替换

再次把命令行分成命令词

展开文件通配

准备I/O重导向(<、>)

运行命令

5、bash的配置文件:按照生效范围划分,存在两类:

全局配置:/etc/profile、/etc/profile.d/*.sh、/etc/bashrc

个人配置:~/.bash_profile    ~/.bashrc

shell登录的两种方式:

交互式登录:

直接通过终端输入账号密码登录

使用su – 切换用户

配置文件执行顺序:/etc/profile、/etc/profile.d/*.sh、~/.bash_profile、~/.bashrc、/etc/bashrc

非交互式登录:

su 登录

图形界面下打开的终端

执行脚本

执行顺序:~/.bashrc、/etc/bashrc、/etc/profile.d/*.sh

按照功能划分:profile类和bashrc类:

profile类:为交互式登录的shell提供配置

全局:/etc/profile、/etc/profile.d/*.sh

个人:~/.bash_profile

功能:用于定义环境变量;运行命令或脚本

bashrc类:为非交互式和交互式登录的shell提供配置

全局:/etc/bashrc

个人:~/.bashrc

功用:定义命令别名和函数;定义本地变量

bash退出任务:保存在~/.bash_logout文件中(用户)

在退出登录shell时运行;

用于创建自动备份或者清除临时文件等。

 

二、命令详解及事例

1、数组:存储多个元素的连续的内存空间,相当于多个变量的集合。

索引:编号从0开始,属于数值索引;

注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0之后开始支持。

Bash的数组支持稀疏格式(索引不连续)

声明数组:

declare  -a  ARRAY_NAME

Declare  -A  ARRAY_NAME:关联数组

数组元素的赋值:

一次只赋值一个元素

ARRAY_NAME[INDEX]=NALUE

weekdays[0]=”sunday”

weekdays[4]=”thursday”

一次赋值全部元素

ARRAY_NAME=(“VAL1” ”VAL2” ”VAL3”…)

只赋值特定元素

ARRAY_NAME=([0]=”VAL1”  [3]=”VAL2”…)

交互式赋值

命令:read -a ARRAY

引用数组元素:${ARRAY_NAME[INDEX]}

注意:省略[]表示引用下标为0的元素

数组的长度(数组中元素的个数):

${#ARRAY_NAME[*]}   ${#ARRAY_NAME[@]}

示例:生成10个随机数保存于数组中,并找出最大值和最小值:

#!/bin/bash
#array
#
declare -a RAND
declare -i MAX=0
declare -i MIN=32766
for I in {0..9};do
    RAND[$I]=$RANDOM
    echo ${RAND[$I]}
    [ "${RAND[$I]}" -ge "$MAX" ] && MAX=${RAND[$I]}
    [ "${RAND[$I]}" -le "$MIN" ] && MIN=${RAND[$I]}
done
    echo "MAX:$MAX"
    echo "MIN:$MIN"

写一个脚本,定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;

要统计其下标为偶数的文件中的行数之和:

#!/bin/bash
#array
#
declare -a FILE
declare -i LINE=0
FILE=(/var/log/*.log)
for i in $(seq 0 $[${#FILE[@]}-1]);do
    if [ $[$i%2] -eq 0 ];then
        let LINE+=$(wc -l ${FILE[$I]} | cut -d" " -f1)
    fi  
done
echo "Lines:$LINE"

2、数组数据处理:

引用数组中的元素:所有元素${ARRAY[@]},${ARRAY[*]}

数组切片:${ARRAY[@]:offset:number}

offset:要跳过的元素个数

number:要取出的元素个数

取偏移量之后的所有元素:${ARRAY:offset}

[root@localhost shelltest]# ing=(a b c d e)
[root@localhost shelltest]# echo ${ing}
a
[root@localhost shelltest]# echo ${ing[3]}
d
[root@localhost shelltest]# echo ${ing[*]:2}
c d e
[root@localhost shelltest]# echo ${ing[*]:2:1}
c

向数组中追加元素:

[root@localhost shelltest]# ing[${#ing[*]}]=f
[root@localhost shelltest]# echo ${ing[5]}
f

输出数组中的某单个元素:unset ARRAY[INDEX]

关联数组:declare -A ARRAY_NAME必须先声明

ARRAY_NAME=([idx_name1]=’val1’ [idx_name2]=’val2’…)

索引编号不是数字,自定义索引

[root@localhost shelltest]# declare -A jing
[root@localhost shelltest]# jing=([a]=aaa [b]=bbb [c]=ccc)
[root@localhost shelltest]# echo ${jing[c]}
ccc
[root@localhost shelltest]# echo ${jing[b]}
bbb
[root@localhost shelltest]# echo ${jing[a]}
aaa

3、字符串处理:字符串切片:

${#var} 返回字符串变量var的长度;

${var:offset} 返回字符串var中从第offset个字符后(不包含)的字符开始,到最后的部分,offset的取值在0到${#var}-1之间(从bash4.2之后,允许为负值)。

${var:offset:number}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分。

${var:  -lengh}:取字符串的最右侧几个字符。冒号后必须有一空白字符,如果不是用空白字符分隔,没有意义。例如:

[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:  -2}
sf
[root@localhost ~]# echo ${var: 5}
jg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:5}
jg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:5:12}
jg21as4asd:a

基于模式取子串:${var#*word} 其中word可以是指定的任意字符

功能:自左而右,查找var变量所存储的字符串中,第一次出现的word,删除字符串开头至第一次出现word字符之间的所有字符。

${var##*word} 同上,不同的是:删除的是字符串开头至最后一次由word指定的字符之间的所有内容。例如:

[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var#*:}
asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var##*:}
asf

${var%word*} 其中word可以是指定的任意字符:

功能,自右往左,查找var变量存储的字符串中,第一次出现的word,删除字符串最后一个字符向左至第一次出现word字符之间的所有字符;例如:

[root@localhost ~]# var=alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var%:*}
alasdjg21as4asd:asdg1:asd:asdf
[root@localhost ~]# echo ${var%%:*}
alasdjg21as4asd

查找替换:

${var/pattern/substi} 查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substi替换之。

${var//pattern/subti} 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substi替换之

${var/#pattern/substi} 查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substi替换之。

${var/%pattern/substi} 查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substi替换之。

[root@localhost ~]# echo ${var/:/@@}
alasdjg21as4asd@@asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var//:/@@}
alasdjg21as4asd@@asdg1@@asd@@asdf@@asf
[root@localhost ~]# echo ${var/#@/vvv}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var/#:/vvv}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var/#/vvv}
vvvalasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var/%/AAA}
alasdjg21as4asd:asdg1:asd:asdf:asfAAA
[root@localhost ~]# echo ${var/%asf/AAA}
alasdjg21as4asd:asdg1:asd:asdf:AAA

查找并删除:

${var/pattern} 查找var所表示的字符串中,删除第一次被pattern所匹配到的字符串

${var//pattern} 删除所有匹配到的字符串

${var/#pattern} 删除行首被匹配到的字符串

${var/%pattern} 删除行尾被匹配到的字符串

${var^^} 把var中的所有小写字母转换为大写

${var,,} 把var中的所有大写字母转换为小写

例如:

[root@localhost ~]# echo $var
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var/%asf/AAA}
alasdjg21as4asd:asdg1:asd:asdf:AAA
[root@localhost ~]# echo ${var//as}
aldjg214d:dg1:d:df:f
[root@localhost ~]# echo ${var^^}
ALASDJG21AS4ASD:ASDG1:ASD:ASDF:ASF
[root@localhost ~]# echo ${a}
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# echo ${a/#*x}
:0:0:root:/root:/bin/bash

pattern皆支持通配符,处理方式基于类似pattern space,不直接改变字符串。

变量赋值:

${var:-value} 如果为空或未设置,那么返回value;否则返回var值。

${var:+value} 如果var不空则返回value

${var:=value} 如果var为空或未设置,那么返回value,并将value赋值给var;否则则返回var的值;

${var:?error_info} 如果var为空或未设置,那么返回error_info;否则分会var的值。

[root@localhost ~]# echo ${var:-AAA}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:+AAA}
AAA
[root@localhost ~]# echo ${var:=AAA}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${aaa:=AAA}
AAA
[root@localhost ~]# echo $aaa
AAA
[root@localhost ~]# echo ${va:?abc}
-bash: va: abc
[root@localhost ~]# echo ${var:?abc}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:-AAA}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${var:+AAA}
AAA
[root@localhost ~]# echo ${var:=AAA}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# echo ${aaa:=AAA}
AAA
[root@localhost ~]# echo $aaa
AAA
[root@localhost ~]# echo ${va:?abc}
-bash: va: abc
[root@localhost ~]# echo ${var:?abc}
alasdjg21as4asd:asdg1:asd:asdf:asf
[root@localhost ~]# 
[root@localhost ~]#

给aaa赋值:若aaaa存在则赋aaaa的值,不存在则赋值123456

[root@localhost ~]# aaa=${aaaa:=123456}
[root@localhost ~]# echo $aaa
123456

为脚本程序使用配置文件,实现变量赋值:

定义文本文件,每行定义NAME=VALUE;在脚本中source此文件即可。

4、declare命令:

-r 将变量设置为只读属性

-i 将变量定义为整型数

-a 将变量定义为数组

-f 显示此脚本前定义过的所有函数名及其内容

-F 仅显示此脚本前定义过的所有函数名

-x 将变量声明为环境变量

-l 将变量值转为小写字母

-u 将变量转为大写字母

[root@localhost ~]# declare -u a=aaa
[root@localhost ~]# echo $a
AAA

间接变量引用:如果第一个变量的值是第二个变量的名字,从第一个变量用用第二个变量的值就称为简介变量引用。bash中提供了两种格式实现间接变量引用:

eval tempvar=\$$variable1

eval命令:eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。

tempvar=${!variable1}

示例:

[root@localhost ~]# n=name
[root@localhost ~]# name=wang
[root@localhost ~]# NAME=${!n}
[root@localhost ~]# echo $NAME
wang
[root@localhost ~]# eval NAME1=\$$n
[root@localhost ~]# echo $NAME1
wang

eval命令示例:

[root@localhost ~]# abc=pwd
  [root@localhost ~]# eval $abc
/root


三、课后练习

1、生成10个随机数,采用冒泡算法进行升序或降序排序。

#!/bin/bash
#sort
#
read -p "ten number: " NUM 
if echo $NUM | grep [[:alpha:]] ;then
    echo "input right number!"
    exit 1
fi
declare -a num=($NUM)
declare -i min=0
echo ${num[@]}
 
for I in `seq 0 $[${#num[@]}-1]`;do
    for J in `seq 1 $[${#num[@]}-1]`;do
        if [ ${num[$J]} -ge ${num[$[$J-1]]} ];then
            min=${num[$[$J-1]]}
            num[$J-1]=${num[$J]}
            num[$J]=$min
        fi
    done
done
 
echo ${num[@]}

原创文章,作者:SilencePavilion,如若转载,请注明出处:http://www.178linux.com/39295

赞 (0)
SilencePavilionSilencePavilion
上一篇 2016-08-24 10:12
下一篇 2016-08-24 10:13

相关推荐

  • 文件通配符练习

    课后资料补充 * : 通配符,代表任意字符(0到多个)? : 通配符,代表一个字符# : 注释/ : 跳转符号,将特殊字符或通配符还原成一般符号| : 分隔两个管线命令的界定; : 连续性命令的界定~ : 用户的根目录$ : 变量前需要加的变量值! : 逻辑运算中的&q…

    Linux干货 2016-08-08
  • RPM及YUM工具介绍及使用(上)

    写在前面 常见的计算机硬件平台大致可以为分:x86、x86_64、amd64、ppc、arm、aarch64。软件平台,在Linux界则是指不同的Linux发行版。 Linux系统中的软件(非源码)由于都是在不同的硬件+软件平台开发编译完成之后发布的,因此同一个软件会区分硬件和软件环境而有不同的软件包。在安装软件时应该选择与自己的硬件和软件平台一致的软件包进…

    Linux干货 2016-12-26
  • 第二周博客作业

    1.Linux上的文件管理类命令都有那些,其常用的使用方法及其相关示例演示。
    2.Bash的工作特性之命令执行状态返回值和命令行展开所涉及的内容及其示例演示。
    3.请使用命令行展开功能来完成以下的练习。
    4.文件的元数据信息有哪些,分别表示什么含义,如何查看?如何修改文件的时间戳信息。
    5.如何定义一个命令的别名,如何在命令中引用另一个命令的执行结果?
    6.显示/var目录下所有以1开头,以一个小写字母结尾,且中间至少出现一位数字(可以有其他字符)的文件或目录。
    7.显示/etc目录下,以任意一个数字开头,且以非数字结尾的文件或目录。
    8.显示/etc目录下,以非字母开头,后面跟了一个字母以及其他任意长度任意字符的文件或目录。
    9.在/tmp目录下创建以tgile开头,后跟当前日期和时间的文件,文件名形如:tfile-2016-05-27-09-32-22
    10.复制/etc目录下所有以p开头,以非数字结尾的文件或目录到/tmp/mytest1目录中。
    11.复制/etc目录下所有以.d结尾的文件或目录到/tmp/mytest2目录中。
    12.复制/etc目录下所有以l或m或n开头,以.conf结尾的文件至/tmp/mytest3目录中。

    2018-03-22
  • 马哥教育网络班19期+第十周课程练习

    1、请详细描述CentOS系统的启动流程(详细到每个过程系统做了哪些事情) CentOS主机按以下顺序启动 (1)POST     加电自检         (2)BIOS    &nbsp…

    Linux干货 2016-07-07
  • Linux进程及作业控制

    inux进程 进程的概念 当一个系统启动时,刚开机是第一个运行的是内核代码!先把内核放到cpu上运行,等内核控制和掌管了一切,有内核启动进程!然后创建第一个进程 init进程  内核空间 用户空间也都已被创建成功!后期的一切管理工作都由init来负责 init不能代表系统完成一些内核特权的执行!但由他负责向内核提交 他…

    Linux干货 2016-09-10
  • 创建CA证书

    创建CA证书 CA证书         CA 也拥有一个证书(内含公钥和私钥)。网上的公众用户通过验证 CA 的签字从而信任 CA ,任何人都可以得到 CA 的证书(含公钥),用以验证它所签发的证书。       &nb…

    Linux干货 2017-07-23