AcWing Linux基础课第三节笔记Shell语法4

12 篇文章 0 订阅

1、该系列为ACWing中Linux基础课,已购买正版,课程作者为yxc
2、为啥写在这儿,问就是oneNote的内存不够了QAQ
3、shell语法好多呀笔记

Shell语法(四)

函数

bash中的函数类似于C/C++中的函数,但return的返回值与C/C++不同,返回的是exit code,取值为0-255,0表示正常结束。

如果想获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(function_name)来获取stdout中的结果。

函数的return值可以通过$?来获取。

命令格式:

[function] func_name() {  # function关键字可以省略
    语句1
    语句2
    ...
}

1、不获取 return值和stdout值

func() {
    name=yxc
    echo "Hello $name"
}

func
===============分割线输出结果==============
Hello yxc

2、获取 return值和stdout值
不写return时,默认return 0,通过$(function_name)获取输出值;

func() {
    name=yxc
    echo "Hello $name"

    return 123
}

output=$(func)
ret=$?

echo "output = $output"
echo "return = $ret"
===============分割线输出结果==============
output = Hello yxc
return = 123

3、函数的输入参数
在函数内,$1表示第一个输入参数,$2表示第二个输入参数,依此类推。

注意:函数内的$0仍然是文件名,而不是函数名。

func() {  # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0
    word=""
    while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
    do
        read -p "要进入func($1)函数吗?请输入y/n:" word
    done

    if [ "$word" == 'n' ]
    then
        echo 0
        return 0
    fi  

    if [ $1 -le 0 ] 
    then
        echo 0
        return 0
    fi  

    sum=$(func $(expr $1 - 1))
    echo $(expr $sum + $1) (在递归里该命令没有输出)
}

echo $(func 10)
===================分割线输出结果==================
55
【sum=$(func `expr $1 - 1`)命令也可以】

关于递归函数里最后的echo没有输出的问题的解释:当参数一直减到0时开始return,注意此时有echo 0,但是并没有输出是因为此层函数结束后回到上一层函数的 sum=$(func $(expr $1 - 1)),不输出的原因就是$(func xxxx)$()会读取函数的stdout而不直接输出出来(大家可以单独写一个函数只有echo xx,然后调用$(func)会发现不会输出),所以sum语句的下一行echo就遵循了这个原则,不会直接输出。当整个递归全部结束,才会由函数外echo $(func 10)中的echo来输出最终结果。如果把函数外的echo $(func 10)改成func 10就是由最后一层递归echo $(expr $sum + $1)输出的55。

例如:
最后是x=$(func),在terminal里是不会输出的;但如果是echo $(func)是会输出的。感觉shell跟c\c++比还是有区别的,c\c++里在函数里cout就会输出值到stdout。

#! /bin/bash

func() {
    name=yxc
    echo "Hello $name"
}
x=$(func)

4、函数的局部变量
可以在函数内定义局部变量,作用范围仅在当前函数内。

可以在递归函数中定义局部变量。

命令格式:

local 变量名=变量值

示例:

#! /bin/bash

func() {
    local name=yxc
    echo $name
}
func

echo $name
===============分割线============
yxc

第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。

exit命令

  • exit命令用来退出当前shell进程,并返回一个退出状态(可以理解为自行设置一个退出状态);使用$?可以接收这个退出状态。
  • exit命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
  • exit退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败

return和exit的共同之处都是返回exit code,区别是return结束当前函数,exit结束整个shell脚本

示例:创建脚本test.sh

#! /bin/bash

if [ $# -ne 1 ]  # 如果传入参数个数等于1,则正常退出;否则非正常退出。
then
    echo "arguments not valid"
    exit 1
else
    echo "arguments valid"
    exit 0
fi
==================分割线==================
acs@9e0ebfcd82d7:~$ chmod +x test.sh 
acs@9e0ebfcd82d7:~$ ./test.sh acwing
arguments valid
acs@9e0ebfcd82d7:~$ echo $?  # 传入一个参数,则正常退出,exit code为0
0
acs@9e0ebfcd82d7:~$ ./test.sh 
arguments not valid
acs@9e0ebfcd82d7:~$ echo $?  # 传入参数个数不是1,则非正常退出,exit code为1
1

文件重定向

每个进程默认打开3个文件描述符:

  • stdin标准输入,从命令行读取数据,文件描述符(可以认为是打开文件的一个id)为0; (C++中的cin,bash的read都是从stdin中读取数据)
  • stdout标准输出,向命令行输出数据,文件描述符为1
  • stderr标准错误输出,向命令行输出数据,文件描述符为2
    可以用文件重定向将这三个文件重定向到其他文件中。

1、重定向命令列表

命令说明
command > filestdout重定向到file中
command < filestdin重定向到file中 (从文件中读命令)
command >> filestdout以追加方式重定向到file中
command n> file将文件描述符n重定向到file中
command n>> file将文件描述符n以追加方式重定向到file中
  • ls -l >文件 (文件列表的内容写入文件a.txt中 覆盖写)
  • ls -al >>文件 (文件列表的内容文件追加到文件aa.txt的末尾)
  • cat 文件1 >文件2 (将文件1的内容覆盖到文件2)
  • echo “内容” >>文件 (将echo的内容追加到文件末尾)

2、输入和输出重定向

echo -e "Hello \c" > output.txt  # 将stdout重定向到output.txt中
echo "World" >> output.txt  # 将字符串追加到output.txt中

read str < output.txt  # 从output.txt中读取字符串

echo $str  
=================================================================
输出结果:Hello World

3、同时重定向stdin和stdout

./test.sh < input.txt > output.txt
./test.sh> output.txt < input.txt 两个命令均可运行

创建bash脚本:

#! /bin/bash

read a
read b
echo $(expr "$a" + "$b")
带引号因为,如果变量a和b的值带空格会被解析成两个参数导致error,
比如a=jalan chao,带引号就不报错

创建input.txt,里面的内容为:

3
4

执行命令:

acs@9e0ebfcd82d7:~$ chmod +x test.sh  # 添加可执行权限
acs@9e0ebfcd82d7:~$ ./test.sh < input.txt > output.txt  # 从input.txt中读取内容,将输出写入output.txt中
acs@9e0ebfcd82d7:~$ cat output.txt  # 查看output.txt中的内容
============================================================
7

示例二:
main.sh接收两个传入参数。格式为 ./main.sh input_file output_file。从input_file中读取一个正整数n,然后将前n个正整数的平方和写入output_file中

#! /bin/bash

input_file=$1
output_file=$2

read n < $input_file
sum=0
for ((i = 1; i <= n; i ++ ))
do
    sqr=`expr $i \* $i`
    sum=`expr $sum + $sqr`
done
echo $sum > $output_file
=================以下为命令================
acs@9e0ebfcd82d7:~$ ./main.sh  input.txt  output.txt

引入外部脚本

类似于C/C++中的include操作,bash也可以引入其他文件中的代码。

语法格式:

. filename  # 注意点和文件名之间有一个空格source filename

示例:
创建test1.sh,内容为:

#! /bin/bash

name=yxc  # 定义变量name

然后创建test2.sh,内容为:

#! /bin/bash

source test1.sh # 或 . test1.sh
echo My name is: $name  # 可以使用test1.sh中的变量

运行:

acs@9e0ebfcd82d7:~$ chmod +x test2.sh 
acs@9e0ebfcd82d7:~$ ./test2.sh 
My name is: yxc

这节内容终于完了哈哈哈哈哈哈哈哈哈累死了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值