【Linux Shell 脚本攻略】Day02

1、数学运算

在Bash shell环境中,可以使用let、(())和[]执行基本的算术操作,而在进行高级操作时,也会使用到expr和bc这两个工具。

1)let命令

使用普通的变量赋值方法定义赋值,存储为字符串,可使用let命令进行基本的算术操作。当使用let时,变量名之前不需要再添加$,如下:

#!/bin/bash

no1=4

no2=5

let result=no1+no2

echo $result


自加操作

$ let no1++


自减操作

$ let no1--


简写形式

let no+=6等同于let no=no+6

let no-=6等同于let no=no-6


2)操作符[]

操作符[]的使用方法和let命令类似:

result=$[ no1 + no2 ]

在[]中也可以使用$前缀,如:

result=$[  $no1 + 5 ]

3)操作符(())

使用操作符(())操作如下:

result=$(( no1 + 5 ))

4)工具expr

expr同样可以用于基本算术操作,如下:

$ result=`expr 3 + 4 `

$ result=$(expr $no1 + 5)

注意有操作符间有无空格的区别:

$ expr 3 + 4

7

$ expo 3+4

3+4

5)工具bc

let命令、运算符(())、运算符[]及工具expr值能用于整数运算,不支持浮点数。

bc是一个用于数学运算的高级工具,这个精密计算器包含了大量的选项。可以使用bc执行浮点数运算,并应用一些高级函数。

$ echo "4*0.56" |bc

2.24

$ no=54

$ result=`echo "$no*1.5" |bc`

$ echo $result

81.0

其他参数可以置于要执行的具体操作之前,同时以分号座位定界符,通过stdin传递给bc。

1)设定小数精度

scale的值表示小数的位数,如下:

$ echo "scale=2;3/8" |bc

0.37

2)进制转换

通过obase和ibase的设置进行进制转换。

$ no=100

$ echo "obase=2;$no" |bc

1100100

$ no=1100100

$ echo "obase=10;ibase=2;$no" |bc

100

[root@iZ2zeafpnt57xvg0qrzjaiZ liubc]#

3)平方及平方根

通过运算符^和sqrt进行平方和平方根的运算。

$ echo "sqrt(100)" |bc

10

$ echo "10^10" |bc       

10000000000

2、文件描述符和重定向

1)文件描述符

文件描述符是与文件输入、输出相关联的整数,用来跟踪已打开的文件。

最常见的文件描述符是stdin、stdout和stderr,0、1、2分别是stdin、stdout、stderr的预留描述符编号。

0 —— stdin(标准输入)

1 —— stdout(标准输出)

2 —— stderr(标准错误)

2)重定向

可以将某个文件描述符的内容重定向到另一个文件中。

可以将输出文本重定向或保存到文件中,如下:

$ echo "This is a sample text 1" > temp.txt

这种方法通过截断文件到方式,将输出文本存储到文件temp.txt中。在把echo命令的输出写入文本之前,temp.txt中的内容会先被清空。

若要不清空原有文件,并将内容追加到目标文件中,可将>替换成>>,如下:

$ echo "This is a sample text 2" >> temp.txt

查看文件内容:

$ cat temp.txt

This is a sample text 1

This is a sample text 2

当命令输出错误信息时,stderr信息就会被打印出来。下面的命令会将stderr文本打印到屏幕上,而不是文件中,由于stdout没有输出,因此没有内容:

$ ls + > out.txt

ls: cannot access +: No such file or directory

下面的命令,将stderr重定向到ou t.txt中:

$ ls + 2> out.txt

$ cat out.txt

ls: cannot access +: No such file or directory

也可以将stderr单独重定向到一个文件,将stdout重定向到另一个文件:

$ cmd 2>stderr.txt 1>stdout.txt

也可以将stderr转换成stdout,使得stderr和stdout都被重定向到同一个文件中,如下:

$ cmd 2>&1 stdout.txt

或者:

$ cmd &> stdout.txt

如果不想让终端输出stderr的信息,可以将stderr重定向到/dev/null,如下:

$ cmd 2> /dev/null

3)tee命令

若要在终端打印stdout,同时将它重定向到一个文件中,可以使用tee,如下:

cmd |tee FILE1 FILE2

在下面的代码中,tee命令接收到来自stdin的数据,它将stdout的一份副本写入到文件out.txt,同时将另一份副本作为后续命令的stdin。命令cat -n将从stdin中接收到的每一行数据前加上行好并写入stdout:

$ echo a1 > a1

$ cp a1 a2

$ cp a2 a3

$ chmod 000 a1

$ cat a* |tee out.txt|cat -n

cat: a1: Permission denied

1 a1

2 a1

查看out.txt的内容:

$ cat out.txt

a1

a1

默认情况下,tee命令会将文件覆盖,-a选项用于追加内容,如下:

$ cat a* |tee -a out.txt|cat -n

4)将文件重定向到命令

可以使用stdin从文件读取数据,如下:

$ cmd < file

5)将脚本内部的文本块进行重定向

例如,向log文件中写入头部数据:

#!/bin/bash

cat<<EOF>log.txt

LOG FILE HEADER

This is a test log file

Function:System statistics

EOF

6)自定义文件描述符

<操作符用于从文件读取数据到stdin。>操作符用于截断模式的文件写入,即数据在目标文件内容被截断后写入。>>操作符用于追加模式的文件写入,即数据被添加到文件的现有内容中,且该目标文件中的原有内容不丢失。

可以使用exec命令创建自定义文件描述符。

创建一个文件描述符进行文件读取,如下:

$ echo this is a test line > input.txt

$ exec 3 < input.txt

$ cat <&3

this is a test line

如果要在此读取,就不能继续使用文件描述符3了,而是需要用exec重新分配文件描述符来进行二次读取。

创建一个文件描述符用于截断写入,如下:

$ exec 4>output.txt

$ echo newline >&4

$ cat output.txt

newline

创建一个文件描述符用于追加写入,如下:

$ exec 5>>output.txt

$ echo appended line >&5

$ cat input.txt

new line

appended line


成功与不成功的命令

当一个命令发生错误并退出时,它会返回一个非0的退出状态;而当命令成功完成后,它会返回数字0。退出状态可以从特殊变量$?中获得。在命令执行之后立即运行echo $?,就可以打印出退出状态。


3、数组

1)定义数组

定义数组的方法如下:

array_var=(1 2 3 4 5 6)

这些值将会存储在以0为起始索引的连续位置上。

也可以将数组定义成一组“索引-值”,如下:

array_var[0]="1"

2)打印数组

打印特定索引的数组元素,如下:

$ echo ${array_var[0]}

1

$ index=5

$ echo ${array_var[$index]}

6

打印数组中的所有值,如下:

$ echo ${array_var[*]}

1 2 3 4 5 6

也可以这样使用,如下:

$ echo ${array_var[@]}

1 2 3 4 5 6

打印数组长度,如下:

$ echo ${#array_var[@]}

6

3)关联数组

在关联数组中,可以用任意文本作为数组索引。

定义数组时,使用声明语句将一个变量名声明为关联数组。如下:

$ declare -A ass_array

声明之后,可以用两种方法将元素添加到关联数组中。

利用内嵌“索引-值”列表的方法,提供一个“索引-值”列表,如下:

$ ass_array=([index1]=val1 [index2]=val2)

使用独立的“索引-值”进行赋值,如下:

$ ass_array[index1]=val1

$ ass_array[index2]=val2

每个数组元素都有一个索引用于查找,普通数组和关联数组具有不通的索引类型。可以通过以下方法获取数组的索引列表:

$ echo ${!array_var[*]}

也可以使用:

$ echo ${!array_var[@}

对于普通数组,这个方法同样可行。

4、别名

别名是一种便捷方式,以省去用户输入一长串命令序列的麻烦。

使用alias命令创建别名。如下:

$ alias new_command='command sequence'

alias命令的作用只是暂时的,一旦终端关闭,所有设置的别名就都失效了。为了使别名的设置一直保持有效,可以将它放入~/.bashrc文件中。当一个新的shell进程生成时,都会执行~/.bashrc中的命令。

$ echo 'alias cmd="command sequence"' >> ~/.bashrc

如果要删除别名,将其对应的语句从~/.bashrc中删除,或者使用unalias命令。也可以使用alias example=,这会取消名example的别名。

创建别名时,如果已经有同名的别名存在,那么原有的别名设置将被新的设置取代。

当要忽略当前定时的别名时,可以使用字符\对命令进行转义,从而执行原本的命令,而不是这些命令的别名。如下:

$ \command

通过在命令前加上\来忽略可能存在的别名设置,总是一个不错的安全实践。因为攻击者可能已经将一些别有用心的命令利用别名伪装成了特权命令,借此来倒去用户输入的重要信息。

5、获取终端信息

tput和stty是两款终端处理工具。

1)获取终端的行数和列数:

tput cols

tput lines

2)打印当前终端名:

tput longname

3)将光标移动到(100,100)处:

tput cup 100 100

4)设置终端背景颜色:

tput setb n)

其中,n可以在0到7之间取值。

5)设置文本前景色:

tput setf n)

其中,n可以在0到7之间取值。

6)设置文本样式为粗体:

tput bold

7)设置下划线的起止:

tput smul

tput rmul

8)删除从当前光标位置到行尾的所有内容:

tput ed)

9)输入密码时,不应该显示输入内容,可以通过stty来实现,如下:

#!/bin/bash

#Filename: password.sh

echo -e "Enter password: "

stty -echo

read password

stty echo

echo

echo Password read

选项-echo禁止将输出发送到终端,而选项echo则允许发送输出到终端。

6、获取、设置日期和延时

在类Unix系统中,日期被存储成一个整数,其大小为自世界标准时间(UTC)1970年1月1日0时0分0秒起所流逝的秒数。这种计时方式称为纪元时或Unix时间。

1)读取日期

$ date

Sun Mar  4 12:35:23 CST 2018

2)打印纪元时

$ date +%s

1520138123

将任意的日期格式转换成纪元时:

$ date --date "Sun Mar  4 12:35:23 CST 2018" +%s

1520138123

选项--date用于提供日期串作为输入。

3)格式化日期

用格式串结合+作为date命令的参数,可以打印对应格式的日期。如下:

$ date "+%d %B %Y"

04 March 2018

4)设置日期和时间

date -s "格式化的日期字符串"

5)检查脚本执行时长

可使用如下代码:

#!/bin/bash

# Filename: time_take.sh

start=$(date +%s)

commands;

statements;

end=$(date +%s)

difference=$(( end - start ))

echo Time taken to execute commands is $difference seconds.

另一种方法则是使用time<scriptpath>来得到执行脚本所花费的时间。

6)日期格式

星期    %a(例如:Sun)    %A(例如:Sunday)

月份    %b(例如:Mar)        %B(例如:March)    %m(例如:03)    %h(例如:Mar)

日        %d(例如:31)

固定格式日期    %D(例如:03/04/18)

年份    %y(例如:18)    %Y(例如:2018)

小时    %I(例如:01)    %H(例如:13)

分钟    %M(例如:06)

秒        %S(例如:01)

纳秒    %N(例如:892982208)

Unix纪元时(以秒为单位)    %s(例如:1520140188)

7)延时

延时通过sleep命令实现,单位为秒。

如下脚本:

#!/bin/bash

# Filename: sleep.sh

echo -n Count:

tput sc

count=0;

while true;

do

  if [ $count -lt 40 ];

  then

    let count++;

    sleep 1;

    tput rc

    tput ed

    echo -n $count

  else exit 0;

  fi

done

在上面的例子中,变量count初始化为0,随后每循环一次便加1,echo语句打印出count的值。用tput sc存储光标位置,在每次循环中,通过命令tput rc恢复之前存储的光标位置,在终端中打印出新的count值。tput ed清除从当前光标位置到行尾之间的所有内容,使得旧的count值被清除并写入新值。循环的一秒钟延时是通过sleep命令实现的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容