#Day8.Shell语言——作为程序设计语言

一、程序设计语言shell以及我们为什么要学

        是的,shell除了作为命令语言外,它也可以像Python一样编写程序。虽然在语法上并不像Python那样简明易懂、功能强大,但仍是我们的必修课。

        在实际的AI开发岗流程中,我们需要会的不仅仅是能够构建AI,同样重要的是我们要将它落实到实地学会如何部署和训练AI。这意味着我们应懂得如何将各种独立的工具(数据工具、Python训练脚本、环境管理工具、云服务)无缝地连接在一起,形成一个自动化、可复现的健壮工作流。在这一方面,Shell编程语言能够帮助我们。

        一句话总结:Shell编程语言并不参与AI的构建。它是AI工程落地实践的必要工具。

二、第一个Shell脚本

        在安装Python时,我们主要解决了两点:解释器和IDE(集成开发环境),Shell也类似。唯一不同的是Shell作为一个更古老的语言它需要的是:解释器和文本编辑器。解释器在Linux系统本身就存在多个。

        一般常用Bourne Again Shell。至于文本编辑器,我们使用touch命令创建一个.sh结尾的文件即可。创建完成后在首行输入#!/bin/bash以调用Bourne Again Shell解释器。#!的作用自然就是告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。

        虽然事实上即便我们创建的是其他格式的文件(比如.txt)且在开头并不声明#!/bin/bash也能正常执行文件,但出于可读性的考量我们最好还是按照这个方式配置。后文再次出现类似的情况时将不再多加赘述。

        现在来一步步带大家走一遍全流程。

mkdir draft    #创建一个文件夹,储存我们练习过程中建立的文件
cd ./draft    #./同样可选,进入创建的draft文件夹

vim demo1.sh    #创建并进入文件demo1.sh
        按i进入插入模式。

#!/bin/bash

echo "Hello World !"    #echo类似Python中的print()函数
        esc退出插入模式,输入:wq写入并退出文件。

bash demo1.sh    #方法一,bash解释器直接执行脚本

chmod +x ./demo1.sh    #方法二,给予文件执行权限然后直接执行文件
./demo1.sh    #此处./是必要的。不使用cd命令时,不以./指定当前文件夹,系统会在环境变量PATH中寻找运行文件。

三、Shell语法

#在这一节,我们将与Python对照着学习,既作复习又作学习

1)变量

1.1变量创建

        与Python一样的是,Shell同样支持通过给变量赋值来创建变量。不同的是:赋值语句中“=”的前后不允许存在空格;

        当然,除了直接赋值,Shell也提供了通过其他变量间接赋值的方法。也与Python有一定区别,会更加复杂。

variable=${other_var}    #推荐
variable=`other_var`    #不推荐,反引号易与单引号混淆


1.2变量引用

        Shell中在引用变量时(例如上文通过变量为变量赋值)必须加$,可以用大括号括起变量两端。在这里,大括号的作用是帮助解释器识别变量的边界。如果没有大括号,这里解释器就会把“auther's”当作一个变量,使程序出现意料之外的状况。

auther = 'Linux'

echo $auther
echo ${auther}
echo "I like ${auther}'s job" #对于一串字符串,单双引号代表不同意义。参照下文第三小节字符串数据类型。


1.3变量命名

        变量的命名方面,与Python保持一致。不得以数字开头,可由数字字母下划线组成,不能与保留字重名...。

1.4只读型变量

        变量的类型方面,Shell提供了一种只读变量。类同只读文本一样,内容不允许更改。

readonly auther

unset auther    #unset删除变量
#unset: Linux: cannot unset: readonly variable


  2)传递参数

        事实上,我们在运行脚本时可以通过指定符号传递参数。命令形似:

bash ./demo1.sh 123
        demo1.sh内部:

echo "Shell传递参数示例:"
echo "不需要传递的当前工作空间:${0}"
echo "传递进来的数字:${1}"
echo "设置了默认值的参数:${2:-567}"

Shell传递参数示例:
不需要传递的当前工作空间:demo1.sh
传递进来的数字:123
设置了默认值的参数:567


            在这里,我们使用了${1}并不是引用了变量1的含义。这仅是$这个符号的特殊用法。除此之外还有其他用法。

${#}                返回传递入脚本的参数的个数

${*}                用一个字符串返回传递进来的所有内容

${@}              每个传入的参数都作为一个字符串输出,具体演示请参照下面的for循环部分

3)数据类型

3.1字符串

一个字符串,在Shell语言中提供了三种创建方式。

var=This is a string    #is: command not found
var='This is a string'
var="This is a string"


        对于第一种方式,无引号。我们并不推荐。这种方式下,空格会被作为分隔符处理,解释器在运行时,会将空格前后作为两个值处理导致报错,过于粗暴。

        对于第二种方式,单引号。可以使用。这种方式下,解释器在运行时会将其作为纯文本处理,不会执行其中的表达式。作用类同Python在字符串前添加了字母r。即便是转义字符也会被当作纯文本处理,不产生任何作用。

        对于第三种方式,双引号。推荐。这种方式下解释器会正常运行。

获取字符串长度:

string = "This is a srtring"

echo ${#string}


字符串拼接:

string2 = "This is another srtring"

echo "${string}:${string2}"


非常简单粗暴,放一起即可。

字符串截取:

${string: start: length}    #从字符串的左边开始截取,类同Python正向索引,也是从0开始
${string: 0-start: length}    #从字符串的右边开始截取,类同Python负向索引

${string#chars}    #从字符串第一次遇到某段字符开始截取(该段字符不会被截取)
${string#*char}    #从字符串第一次遇到某 “个” 字符开始截取(该字符不会被截取)

${string##chars}    #从字符串最后一次遇到某段字符开始截取(该段字符不会被截取)

${string%chars}    #截止到字符串第一次遇到某段字符(该段字符不会被截取)
${string%char*}    # *的含义是忽略字符,所以在反向截取时*应当放在右侧

3.2数组

array=(1 2 3)


        使用小括号创建,内部元素以空格分隔开;

        且仅支持一维数组,其中的某个元素不可以为数组;

        引用变量时仅返回数组里的第一个值;

${array[index]}    #读取单个元素
${array[@]}    #读取全部元素,且保持元素不变
${array[@] :1 :2}    #切片,索引类同Python,但是会取末尾值。在这输出是:2 3


3.3关联数组

        类同Python中的字典类型数据,但是它的创建需要特别声明。

declare -A dict    #关联数组dict创建方法一
dict["google"]="www.google.com"
dict["baidu"]="www.baidu.com"

declare -A dict=(["google"]="www.google.com" ["baidu"]="www.baidu.com")
#方法二索引方式也是通过键(key)索引。语法与字符串类似。
echo ${dict[@]}    #输出所有数据

echo ${#dict[@]}    #输出元素个数需要注意的是计算元素个数的时候如果不加[@],将返回0
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐