苗木水蜡多少钱一株?

小说:苗木水蜡多少钱一株?作者:顺北更新时间:2019-05-27字数:39541

shell是Linux操作系统的用户接口,我们经常需要编写脚本让操作系统自动执行一系列指令的需求,本文将简单介绍开发shell脚本的所需的语言特性。

shell脚本是指令序列,其指令可以直接在终端中执行。同样地,终端中的指令也可以写到脚本中。

脚本文件通常以.sh作为后缀名,第一行以#!开头指定执行脚本的程序:

#!/usr/bin/bash

#!开头的第一行被称为Hashbang或Shebang。 而#是shell脚本中的行注释符。

通常有三种执行脚本的方式:

  • sh start.sh: 在终端中创建一个sh子进程执行脚本, 执行者需要拥有脚本的读权限。
    该方式实际上是将脚本路径作为参数传递给了sh命令。
  • source start.sh: 在终端中执行脚本,相当于将脚本中的指令逐条复制到终端执行。
    脚本中局部变量将保留在终端环境变量中, 脚本的pid和工作目录等环境也与终端一致。
  • ./start.sh: 根据HashBang指定的程序,在子进程中执行脚本。

sh命令有一些有用的选项帮助我们开发和调试脚本:

  • sh -n start.sh:对脚本进行语法检查, 不实际执行脚本
  • sh -x start.sh: 把将要执行的命令输出到stderr便于进行调试

变量

shell中变量是弱类型的, 变量名只能包含字母、数字或下划线"_",首字符只能为字母。

shell主要面向文本处理而非数据计算,因此变量默认类型为字符串型。

A=abc
echo $A

变量在使用前无需声明,在为变量赋值时=左右不能添加空格。

A = abc会被shell解释为执行指令A,参数为=abc

$为变量标志符, echo $A指令将显示变量A的内容abc, 为了明确指定变量名也可以写作${A}

A=a
AB=ab
echo ${A}B

$(cmd)可以把命令的输出作为返回值, 如:

PWD=$(pwd)

变量$PWD存储了当前的工作目录路径。

在shell中可以直接书写字符串,但仍建议用单引号或双引号标识字符串。

在单引号标识的字符串中$不被作为变量标识符, 而双引号则会将$替换为变量内容。

A="abc"
echo "$A" # $A
echo "$A" # abc

字符串拼接不需要任何运算符,只需要将它们写在一起即可:

A="abc"
B="123"
echo "$A+$B"  # abc+123
echo "$A$B"  # abc123
echo "$Adef"  # abcdef

全局变量

变量按照作用域可以分为局部变量和全局变量,上文示例中定义的变量都是局部变量, 作用域仅限执行脚本的进程。

子进程可以继承父进程的全局变量,export指令用于定义全局变量:

export A=abc

整型变量

shell仅支持整型计算, declare命令可以声明整型变量,let指令用于算术运算:

declare -i a=1
let a=a+1
echo $a  # 2
let a+=1
echo $a  # 3

let指令支持算术运算符包括:

  • +:加法
  • -: 减法
  • *: 乘法
  • /: 除法
  • **: 乘方
  • %: 取余

let指令也支持算术运算符对应的算术赋值运算符,如+=

数组

bash中可以使用圆括号定义数组,元素之间用空格分割,数组下标从1开始:

arr=(1 "a" "abc")
echo ${arr[1]}

也可以直接使用下标定义数组:

arr2[1]=1
arr2[2]=2

该方法同样可以用于修改已存在的数组。

特殊变量

shell中预定义了一些特殊变量,通过这些变量可以获得环境信息:

  • $$: 执行脚本的进程ID(pid)
  • $?: 上一条命令的返回值
  • $!: 上一条后台指令的执行进程的ID

上述变量在交互式终端中同样有效。

还有一些变量可以获得执行脚本时传入的参数:

  • $0: 脚本的文件名
  • $1~$n: 传给脚本的第n个参数
  • $#: 传入参数的个数
  • $@: 参数列表
  • $*: 单个字符串形式的参数列表

流程控制

if

declare -i a=90
if [ $a -gt 80 ]; then
    echo "A"
elif [ $a -lt 60 ]; then
    echo "C"
else
    echo "D"
fi

结束标志fi即是if反写, 我们还将在其它地方遇到bash的这种命名风格。

注意,[]旁边的空格不可省略。

-lt, -gt用于进行整型的大小比较:

  • -eq: 等于(equal)
  • -ne: 不等于(not equal)
  • -gt: 大于(greater)
  • -ge: 大于等于(greater-equal)
  • -lt: 小于(less)
  • -le: 小于等于(less-equal)

进行复合逻辑判断也很简单:

if [ $a -gt 60 -a ( ! $a -gt 90 -o $a eq 91 ) ]; then
    echo "make no sense"
fi
  • !: 非
  • -a: 且and
  • -o: 或-o

逻辑运算遵循短路计算原则。

<, >等运算符在[]中只能用于字符串的比较, 而在[[]]<, >可以用于整型和字符串的大小比较, 也可以使用&&||来书写逻辑表达式。

if的条件判断不一定使用[][[]]表达式,它可以是任何一个命令。命令的返回值为0则if判断为真, 非0判断为假。

[][[]]转义表达式也可以像普通指令一样执行,判断为真则返回0,假则返回非0值。

[ 2 -gt 1 -a 3 -lt 4 ] && echo "ok"

除此之外,if还可以进行更多种类的条件判断:

判断字符串相等

if [ ${NAME} = "tmp" ]; then
    echo "name is tmp"
fi

判断文件是否存在

if [ -e tmp ]; then
    echo "tmp exists"
fi 

判断tmp是否存在,tmp可以是目录或文件。

判断是否为普通文件

if [ -f tmp ]; then
    echo "file tmp exists"
fi

判断tmp是否为文件,tmp不能是目录。

判断是否为目录

if [ -d tmp ]; then
    echo "directory tmp exists"
fi

判断是否具有执行权限

if [ -x tmp ]; then
    echo "tmp is executable"
fi

不判断文件是否可执行,只判断是否拥有x权限。 因此,tmp为有x权限的目录时也会判断为真。

类似的还有,-w判断是否拥有写入权限, -r判断是否拥有读取权限。

判断是否为空文件

if [ -s tmp ]; then
    echo "file is not empty"
fi

case

case类似于其它语言中的switch语句:

case ${NAME} in
    "a")
        echo "name is a"
        ;;
    "b")
        echo "name is b"
        ;;
    *)
        echo "other names"
        ;;
esac

从第一个匹配的标签开始执行, 两个标签之间必须有;;*)是其它标签都不匹配时的默认标签。

for

for循环可以遍历一个序列:

for i in $(seq 1 10); do
    echo $i
done
# echo: 1 2 3 ... 10

一些命令的输出也可以作为序列:

for i in $(ls); do
  echo $i
done

遍历所有参数:

for arg in "$@"; do  
    echo $arg  
done 

另一种形式的for循环:

for (( i=0; i<100; i++)); do
    echo $i
done

while

declare -i i=0
while [ $i -lt 10 ]; do
    echo $i
    i=$i+1
done

while(true)这样的死循环也很容易:

declare -i i=0
while ; do
    echo $i
    [ ! $i -lt 10 ] && break
    i=$i+1
done

函数

shell提供了定义函数的功能, 函数就像是脚本中的子脚本:

range() {
    for (( i=0; i<${1}; i++)); do
        echo $i
    done
    return ${1}
}

range 100

函数同样使用位置参数$1~$n来访问参数,$0为函数的名称, $@, $#等变量的含义不变。

进程间通信

管道

管道用于将上一条指令的输出作为下一条指令的输入:

ls | grep ".zip"

xargs

有一些指令不支持使用管道传递参数,因此需要xargs命令

find ~ | xargs ls 

xargs会以空格为分隔符将输入分隔为参数,然后将参数传给ls。

重定向

重定向用于将命令的输入输出从标准流重定向到文件。标准流包括:

  • stdin: 标准输入流,文件描述符为0
  • stdout: 标准输出流,文件描述符1
  • stderr: 标准错误流,文件描述符2

输出到文件,覆盖原有内容:

echo "hello" > 1.txt 

输出到文件, 追加到文件尾:

echo "hello" >> 1.txt

从文件输入:

wc -l < 1.txt

重定向标准错误输出流:

cmd 2> 2.txt

将标准错误输出追加到文件:

cmd 2>> 2.txt

将标准错误和标准输出一同重定向到文件:

cmd > 1.log 2>&1

2>&1是将stderr重定向到stdout。

后台执行

shell可以执行一行指令后立即返回, 返回后可以通过$?变量获得执行进程的ID:

$ sleep 10 &
[1] 79403
$ echo $!
79403

当前文章:http://www.cnsdbtzg.com/20183uc9bto2cp/index.html

发布时间:2019-05-27 02:52:52

5公分榆叶梅批发基地在哪里? 哪里有雪松容器苗,偷偷告诉你一家又好又便宜的基地! 红刺梅种植间隔多远一棵? 80公分龙柏球多少钱一棵 由黑松、油松、马尾松中提取出来的松花粉它有什么功效 大叶黄杨和冬青的区别有哪些? 新疆碧桃价格便宜吗? 日本海棠一平方米能种多少株? 草坪种植对土质要求高不高,什么样的土不能种? 适合草鱼吃的牧草品种有哪些?

67268 99197 86232 19418 26135 74781 95610 15030 21470 54668 59772 12144 54956 39077 85920 50681 30471 49189 93866 59897 99326 61602 14031

我要说两句: (0人参与)

发布