linux shell求最大公约数,linux shell详解

shell工作原理

Linux系统提供给用户的最重要的系统程序是Shell命令语言解释程序。它不属于内核部分,而是在核心之外,以用户态方式运行。其基本功能是解释并执行用户打入的各种命令,实现用户与Linux核心的接口。系统初启后,核心为每个终端用户建立一个进程去执行Shell解释程序。它的执行过程基本上按如下步骤:

(1)读取用户由键盘输入的命令行。

(2)分析命令,以命令名作为文件名,并将其它参数改造为系统调用execve( )内部处理所要求的形式。

(3)终端进程调用fork( )建立一个子进程。

(4)终端进程本身用系统调用wait4( )来等待子进程完成(如果是后台命令,则不等待)。当子进程运行时调用execve( ),子进程根据文件名(即命令名)到目录中查找有关文件(这是命令解释程序构成的文件),将它调入内存,执行这个程序(解释这条命令)。

(5)如果命令末尾有&号(后台命令符号),则终端进程不用系统调用wait4( )等待,立即发提示符,让用户输入下一个命令,转⑴。如果命令末尾没有&号,则终端进程要一直等待,当子进程(即运行命令的进程)完成处理后终止,向父进程(终端进程)报告,此时终端进程醒来,在做必要的判别等工作后,终端进程发提示符,让用户输入新的命令,重复上述处理过程。

shell语法

变量赋值:

name=value

语法注意:=左右千万不能有空格,不然bash会报错,这个和其它语言不一样,比如javascript,php之类的,之前经常容易犯这个错误,写习惯了别的语言。

变量引用:

弱引用: "", 其内部的变量引用会被替换为变量值;

强引用:'',其变量的变量引用会保持原有字符;

命令引用:`COMMAND`, $(COMMAND),引用命令的执行结果;

声明为整型:

declare -i name=3

let name=2

运行脚本

事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后由bash进程负责解析并运行此逻辑;

启动脚本:

(1) # bash /PATH/TO/SCRIPT_FILE

(2) 给shell脚本一个执行权限,

# ./PATH/TO/SCRIPT_FILE

条件测试:

test EXPRESSION

[ EXPRESSION ]

语法注意:[的右边和]的左边一定要有空格,和赋值刚好相反

整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;

$A -gt $B:是否大于;是则为“真”,否则为“假”;

$A -ge $B: 是否大于等于;

$A -lt $B:是否小于;

$A -le $B: 是否小于等于;

$A -eq $B: 是否等于;

$A -ne $B:是否不等于;

字符串测试:ASCII数值越大,字符比较时其值越大;

"$A" > "$B":是否大于;

"$A" < "$B":是否小于;

"$A" == "$B":是否等于;

"$A" =~ PATTERN:模式匹配;

"$A" != "$B":是否不等于;

-z "$A":是否为空;空则为“真”,否则为“假”

-n "$A":是否不空;不空则“真”,空则为“假”

注意:引用字符串变量$A和$B比较时,变量$A和$B左右两侧都需要加"",这点有和别的语言不一样,像php判断if ($A == $B)即可,而bash必须为if [ "$A" == "$B" ],这个错误之前经常犯

文件测试:测试文件的存在性以及属性;

-e $file: 是否存在;存在则为“真”,否则为“假”;

-a $file: 同上;

-f $file:文件是否存在且为普通文件;

-d $file:文件是否存在且为目录;

-h $file:是否存在且为符号链接文件;

-L $file: 同上

-b $file:是否存在且为块设备文件;

-c $file:是否存在且为字符设备文件;

-S $file:是否存在且为套接字文件;

-p $file: 是否存在且为管道文件;

-r $file: 当前用户对文件是否拥有读权限;

-w $file:当前用户对文件是否拥有写权限;

-x $file:当前用户对文件是否拥有执行权限;

-u $file:文件是否拥有SUID权限;

-g $file:文件是否拥有SGID权限;

-k $file:文件是否拥有sticky权限;

-O $file: 当前用户是否为指定文件的属主;

-G $file: 当前用户是否为指定文件的属组;

双目操作符:

$file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的;

$file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的;

$file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件的硬链接;

组合测试:

与:[ CONDITION1 -a CONDITION2 ] 例子:[ -n "$str" -a "$str" == "haha200142323" ]

或:[ CONDITION1 -o CONDITION2 ]

非:[ ! CONDITION1 ]

多个语句连环执行:

与:COMMAND1 && COMMAND2  如果COMMAND1执行成功,则执行COMMAND2

或:COMMAND1 || COMMAND2  如果COMMAND1执行不成功,则执行COMMAND2

非: ! COMMEND

特殊设备:

/dev/null: 空,bit buckets,吞下所有数据,并直接丢弃;

/dev/zero:吐出一堆0;

位置参数变量:

#bash test10.sh($0变量值) 123($1变量值) 333($2变量值)

特殊变量:

$?: 命令的状态结果;

$#: 传递给脚本或函数的参数的个数;

$*和$@: 引用传递给脚本或函数的参数列表;

算术运算:

+, -, *, /, %(求余), **(乘方)

-=, *=, /=, %=,++,--

例子:let count++,let count+=1,let count++

语法:

1.$[$A+$B], 例子:echo $[1+4],输出5

2.$(($A+$B)),例子:echo $((1+4)),输出5,我也经常用该方式运行复杂运算。比如(1+4)*5,用该方式为$(((1+4)*5)),输出25

3.let c=$a+$b

4.$(expr $a + $b) 注意:+左右两边一定都要有空格

流程控制语句

if语句if [ CONDITION1 ]; then

片段1

elif [CONDITION2]; then

片段2

else

片段3

fi

case语句case $VARIABLE in

PATTERN1)

语句1

;;

PATTERN2)

语句2

;;

PATTERN3)

语句3

;;

*)

语句4

;;

esac

注意PATTERN1,PATTERN2,PATTERN3可使用glob模式的通配符:

*: 任意长度的任意字符;

?: 任意单个字符;

[]: 指定范围内的任意单个字符;

a|b: 多选1;

for语句

方式一:for i in $var; do

echo $i

done

方式二:cnt=100

for (( i=1;i<=$cnt;i++ )); do

echo $i

done

while语句

方式一:while [ $n -lt 100 ]; do

echo $n

done

方式二:while read line; then

echo $line

done 

该方式可以取文件中的每一行($line即为每行的内容)

until语句i=0

until [ $i -lt 100 ]; do

echo $i

let i++

done

函数function fname() {

语句块

}

这里我使用其他编程语言通用的方式把

函数返回的内容只可以用$?返回,但貌似只支持0-255的返回值,而且不能用=将函数返回结果赋值给变量,比如:#!/bin/bash

function sum() {

return $(($1+$2))

}

sum 1 2

echo $?

v=$(sum 1 2)

echo $v

返回结果:[root@localhost ~]# bash test10.sh

3

[root@localhost ~]#

由此可以看出$?能够返回函数的结果,而复制的$v变量为空。

对于$?只支持0-255返回值,我们再来一个实例#!/bin/bash

function sum() {

return $(($1+$2))

}

sum 100 200

echo $?

返回结果:[root@localhost ~]# bash test10.sh

44

[root@localhost ~]#

这个结果一看怎么可能为44.

为解决这个情况,我又将脚本改了下:#!/bin/bash

declare v

function sum() {

v=$(($1+$2))

}

sum 100 200

echo $v

我们再来看看返回结果:[root@localhost ~]# bash test10.sh

300

[root@localhost ~]#

结果正确了,我的思路是申请了一个全局变量v,再在函数中将函数结果赋值给v。

吐槽:bash对于这块实在太坑爹了,有没有更好的方法将函数返回值赋值个变量,欢迎大神告诉我一下,哈哈!

数组

申明变量:

传统数组:索引为数字,从0开始编号;

declare -a ARRAY_NAME

关联数组:索引可以自定义,可以使用任意字符串做索引;

declare -A ARRAY_NAME

支持稀疏格式

赋值:

一次只赋值一个元素

array[index]=value

一次赋值全部元素

array=("val1" "val2" ...)

指定索引进行赋值

array=([0]="val1" [3]="val2")

read -a array

获取数组长度:

${#a[@]}或者${#a[*]}

得到整个数组:

${a[@]}或者${a[*]}

读取数组指定位置:

${a[index]}

删除数组指定位置:

unset a[index]

切分数组:

${a[@]:起始位置:长度}

替换数组:

${a[@]/查找字符/替换字符}

循环数组#!/bin/bash

a=(1 2 30 4 5)

for i in ${a[@]}; do

echo $i

done

小练习:利用bash生成10个随机数值,保存于数组中;要此些数组从大到小降序排列;#!/bin/bash

declare -a a

declare -i sum=10

for (( i=0;i

a[$i]=$RANDOM

done

count=${#a[@]}

for (( i=0;i

for (( j=i+1;j

if [ ${a[i]} -lt ${a[j]} ]; then

temp=${a[i]}

a[i]=${a[j]}

a[j]=$temp

fi

done

done

echo ${a[@]}

返回结果:[root@localhost ~]# bash test10.sh

31870 27033 25714 22587 21793 12488 11529 7180 4051 1751

[root@localhost ~]#

read命令

作用:和用户交互输入数值到一个变量中去

-a:上面已经提到,读一个数组

-p:提示用户输入变量之前输出的字符

-t:用户输入变量的超时时间

实战演练如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;#!/bin/bash

file=$1

if [ -z "$file" ]; then

echo "params error!";

exit 1

fi

if [ ! -e "$file" ]; then

mkdir -p $file

else

echo "$file is exist.."

file $file

fi

2.写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互;#!/bin/bash

read -p 'please input two integer value:' a b

if [ -z "$a" ]; then

echo 'please input a value'

exit 1

fi

if [ -z "$b" ]; then

echo 'please input two params'

fi

if [ $a -eq $b ]; then

echo "${a} is equal to ${b}"

elif [ $a -gt $b ]; then

echo "${a} is greater than ${b}"

else

echo "${a} is smaller than ${b}"

fi

3.求100以内所有奇数之和(至少用3种方法)#/bin/bash

declare -i sum=0

declare -i i=1

while [ $i -lt 100 ]; do

let sum+=$i

let i+=2

done

echo $sum

4.写一个脚本实现如下功能:

(1) 传递两个文本文件路径给脚本;

(2) 显示两个文件中空白行数较多的文件及其空白行的个数;

(3) 显示两个文件中总行数较多的文件及其总行数;#!/bin/bash

read -p 'please input two file path:' file1 file2

if [ -z "${file1}" ]; then

echo "file1 param is empty.."

exit 1

fi

if [ ! -f "$file1" ]; then

echo "$file1 is not a file"

exit 2

fi

if [ -z "$file2" ]; then

echo 'file2 param is empty..'

exit 3

fi

if [ ! -f "$file2" ]; then

echo "${file2} is not a file"

exit 4

fi

kb_num1=$(grep -E '^$' $file1 | wc -l | cut -d' ' -f1)

kb_num2=$(grep -E '^$' $file2 | wc -l | cut -d' ' -f1)

total_num1=$(wc -l $file1 | cut -d' ' -f1)

total_num2=$(wc -l $file2 | cut -d' ' -f1)

if [ $kb_num1 -gt $kb_num2 ]; then

echo "the more space lines is ${file1}, space lines is ${kb_num1}"

elif [ $kb_num1 -lt $kb_num2 ]; then

echo "the more space lines is ${file2}, space lines is ${kb_num2}"

else

echo "${file1} space lines is equal to ${file2}. and the space lines is ${kb_num1}";

fi

if [ $total_num1 -gt $total_num2 ]; then

echo "the more total lines is ${file1}, total lines is ${total_num1}"

elif [ $kb_num1 -lt $kb_num2 ]; then

echo "the more total lines is ${file2}, total lines is ${total_num2}"

else

echo "${file1} total lines is equal to ${file2}. and the total lines is ${total_num1}";

fi

5.写一个脚本

(1) 提示用户输入一个字符串;

(2) 判断:

如果输入的是quit,则退出脚本;

否则,则显示其输入的字符串内容;#!/bin/bash

read -p 'please input a string:' str

if [ -z "$str" ]; then

echo 'the string can not be empty'

exit 1

fi

if [ "$str" == "quit" ]; then

exit 0

else

echo $str

fi

6.写一个脚本,打印2^n表;n等于一个用户输入的值#!/bin/bash

read -p "please input a integer value:" -n1 n

for (( i=0;i<=$n;i++ )); do

let cv=2**$i

echo "2^${i}=${cv}"

done

7.写一个脚本,写这么几个函数:

函数1、实现给定的两个数值的之和;

函数2、取给定两个数值的最大公约数;

函数3、取给定两个数值的最小公倍数;关于函数的选定、两个数值的大小都将通过交互式输入来提供。#!/bin/bash

declare -i totalvalue

declare -i my

declare -i mb

function add() {

totalvalue=$(($1+$2))

}

#求最大公约数

function maxyin() {

declare -i m

if [ $1 > $2 ]; then

m=$2

else

m=$1

fi

while [ $m -gt 1 ]; do

if [ $(($1 % $m)) -eq 0 ] && [ $(($2 % $m)) -eq 0 ]; then

my=$m

break;

fi

let m--

done

my=1

}

#求最小公倍数

function minbei() {

declare -i n

if [ $1 > $2 ]; then

n=$1

else

n=$2

fi

while true; do

if [ $(($n % $1)) -eq 0 ] && [ $(($n % $2)) -eq 0 ]; then

mb=$n

break;

fi

let n++

done

}

read -p "please input two integer value to calculate the sum:" i1 j1

add $i1 $j1

echo "${i1}+${j1}=${totalvalue}"

read -p "please input two integer value to get max gongyueshu:" i2 j2

maxyin $i2 $j2

echo "${i2} with ${j2} the max gongyueshu is ${my}"

read -p "please input two integer value to get min beishu:" i3 j3

minbei $i3 $j3

echo "${i3} with ${j3} the min beishu is ${mb}"

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值