Linux学习笔记之七(shell脚本的基本语法)

Shell

  • 1、Shell脚本
  • 2、常用运算符
  • 2、特殊语法
  • 4、关于变量的一些命令
    • 4.1、echo
    • 4.2、export
    • 4.3、read
    • 4.4、declare/typeset
    • 4.5、local
    • 4.6、unset
  • 5、基本逻辑语法
    • 5.1、if判断
    • 5.2、for循环
    • 5.3、while循环
    • 5.4、case语句
  • 6、函数定义
  • 7、多脚本链接

1、Shell脚本

学习shell脚本开发之前,必须得有一些基础的Linux相关知识,比如环境变量和shell指令的等内容。
了解Linux的系统环境变量和shell命令可以看看我之前发过的两篇文章。
Shell命令(Linux操作命令笔记)
Linux学习笔记之二(环境变量)

再说回shell脚本和shell命令,简单来说,我们在Linux终端中敲下的大多数指令都是shell指令,比如cd , ls, pwd之类的。而 shell脚本就是在一个文件中把这些shell指令依次写在一起,然后让其自动依次执行。这样我们就不需要在终端一条条的去执行了。来看个例子吧。
例程目的:我想切换到$HOME/target目录,并且列出target目录下的所有文件。
首先我先新建一个test.sh的文件,然后往里面写入对应的shell指令。shell脚本文件的第一句话必须是:

#! /bin/bash

写这句话相当于在告诉Linux系统,我写的这个文件是shell脚本,请用bash解释器来解释这个脚本。
在这里插入图片描述
最后执行这个脚本就可以看到我target文件夹下的所有文件了。
在这里插入图片描述
常用的shell指令不妨移步

2、常用运算符

等于号

-eq
note: equal

不等号

-ne
note: not equal

大于号

-gt
note: greater than

大于或等于号

-ge
note: greater than or equal to

小于号

-lt
note: less than

小于等于号

-le
note: less than or equal to

逻辑与

-a
eg: [ $a -eq $b -a $a -eq $c ]		#a等于b于a等于c

逻辑或

-o
eg: [ $a -eq $b -o $a -eq $c ]		#a等于b或a等于c

比较运算符号大概就这些,note后面是缩写符号的整体意思,希望能够帮助记忆。但一点需要值得注意,以上这些特殊字符之用于判断整数与整数之间的关系,而不能用于判断字符串。如果想要判断字符串还得用 = = == == ! = != !=号这些,同时这些常规符号也兼容整数判断。至于逻辑运算符则也可以用&&, ||代替上述的-a和-o。
下面举几个例子来看一下-eq和 = = == ==的区别。

name="lihua"
age=18
[ "$name" -eq "lihua" ];[ "$name" == "lihua" ];[ "$age" == 18 ];

此外,在用$符号对变量取值的时候,最后还是加上一对双引号,这样可以避免很多错误。比如下面这个例子:

name="li hua"
[ $name == "li hua" ][ "$name" == "li hua" ]

如果不加双引号,那$name等于li hua,第一条语句就变成了下面这个样子,显然会报错。

li hua == "li hua"

加了引号就变成。

"li hua" == "li hua"

并且加引号只是把这个变量视为一个整体,并不改变数据本来的属性,是字符串的还是字符串,是整形的还是整形。

2、特殊语法

  • -r:判断给定文件是否是可读文件。
  • -w:判断给定文件是否是可写文件。
  • -x:判断给定文件是否是可执行文件。
  • -d:判断给定参数是否是一个文件夹。
  • -f:判断给定参数是否是一个文件。
  • -s:判断一个文件是否存在并且是否非空。
  • -z:判断给定的字符串是否为空字符串。
  • -n:判断给定的字符串是否为非空字符串。

以上这些都是一些常见的单选项标记符。判断为真则返回1,否则返回。常用于if语句中,比如我们想判断home目录下的object_file是不是可执行文件,可以做如下操作。

if [ -x $HOME/object_file ];thenecho "it is a execuate file"
fi

除了以上这些特殊标记符,还有许多特殊状态变量,如下:

  • $0:获取文件名
  • $n:获取输入的第n个参数
  • $?:获取上一条命令执行的结果,任何bash语句执行结果只有两种,执行成功为0,否则非0。
  • $#:获取传递的参数的总个数。
  • $*:获取脚本所有参数,加引号则表示“$1 $2 … $n ”。
  • $@:获取脚本所有参数,加引号则表示" $1 “,” $2 “,” $n "。 常用于for循环读取参数。
  • $!:获取上一个进程的pid号。
  • $$:获取当前shell脚本的pid号。
  • $_:获取上一次命令的最后一个参数。

看来$ 这个符号在Linux中还挺重要的,个人感觉它有点”取值“的意味,我们取一个变量也会用到$, 比如 $variable 。
最后我写一个脚本把这些特殊状态变量都用上,来看看以上这些特殊变量到底怎么用的。
在这里插入图片描述
执行一下看看效果:
在这里插入图片描述

4、关于变量的一些命令

下面介绍一些出现频率比较高的命令,但我仅讲一些常见的应用,不求全面详细。

4.1、echo

echo常用于打印变量。可以选择是否添加e和n参数,前者使echo可以识别转移字符,后者让echo打印之后不换行(echo默认打印后换行)。
举几个例子:

echo "hello"
echo -e "hello\n"		#可以识别\n
echo -n "hello"			#打印后不换行
echo -en "hello\t"		#识别转义字符且不换行
echo -ne "hello\t"		#效果同上

从上面例子可以看出,echo的参数可以自由组合,且不必考虑顺序,实现效果叠加。其他命令也同样可以。

4.2、export

export可以将变量转化成环境变量,所以我们经常在配置环境变量的时候用到这个命令。

export PATH=$PATH:$HOME/

4.3、read

在shell脚本中使用read命令正如在C语言中使用scanf命令或在python中使用input一样,可以获取用户的输入字符串。它可选的两个参数有p和t两个参数,前者可以显示提示符,后者可以设置等待用户输入的时间。
上个例子,这里我编写一个read.sh的脚本。

#! /bin/bashread -p "please enter a number: " num_1read -p "please enter another number: " -t 5 num_2echo -e "\nthe first number is $num_1"if [ -n "$num_2" ];thenecho "the second number is $num_2" 
elseecho "there is no the second number"
fi

接着,我故意第二个参数不输入,我们来看看结果。
在这里插入图片描述

4.4、declare/typeset

declare和typeset的功能基本一样,所以这里只说declare。
由于shell和python一样,都是弱定义型语言,即变量的类型取决于它所接受到值的类型,无需提前规定好。但弱定义偶尔也有一些不好地方,比如我们本来希望它是一个整型变量,它却因各种原因变成字符串类型。比如read会把数字也视为字符串。。
而declare的主要作用就是声明变量类型,让变量的类型不至于”跑偏“。它常用的参数有以下这些:

  • -a:将变量定义成数组类型。
  • -i:将变量定义成整数类型。
  • -x:将变量定义成环境变量。
  • -r:将变量定义为只读变量,同时该变量无法被unset。

看个例子:

declare -i num				
read -p "please enter a number: " num

这样就可以保证num这个变量就是一个整型了。
再来看看数组怎么用:

#! /bin/bashdeclare -a num
read -p "please enter a number: " num[0]
read -p "please enter another number: " -t 5 num[1]
echo -e "\nthe first number is ${num[0]}"
if [ -n "$num[1]" ];thenecho "the second number is ${num[1]}" 
elseecho "there is no the second number"
fi

其实还是用[ ]来索引数组里面的值,但由于$的优先级高于[ ],所以记得用{ }来使num先索引再取值。除了用declare定义,我们也可以用弱定义的方式定义一个固定长度的数组。

num[0]=1
num[1]=2
..

4.5、local

声明一个变量是一个局部变量,由于shell语言中不同于大多数程序语言,在其函数内部声明的变量不会被自动视为局部变量。所以有时候为了使函数中的变量是局部变量就会用到local命令。
比如下面这个例子,在test这个函数内声明了一个var的局部变量,如果在函数外打印它就会报错。

#! /bin/bashfunction test{local var=1
}echo "$var"

4.6、unset

unset就比较简单了,其功能是删除一个变量。如下,删除var变量之后再调用echo是会报错的。

#! /bin/bashvar="test"
unset var
echo "$var"

看到unset便自然的想到是否有set,其实是有的,只不过它们的功能大相径庭,set主要用于显示所有环境变量。所以与unset相反的作用的更像是typeset。

5、基本逻辑语法

5.1、if判断

基本用法如下,注意该空格的地方不能省略,不该空格的地方不能多加。

#! /bin/bashage=18
if [ "$age" -gt 18 ];thenecho "adult"
elseecho "child"
fi

在shell脚本中的中括号的主要用于条件测试,我们在看看if和逻辑预算符号一起使用的例子。

#! /bin/bashage=21
if [ "$age" -eq 18 ] && [ "$age" -lt 20 ];
thenecho "yes"
elseecho "no"
fi

5.2、for循环

#! /bin/bashfor i in {1..4};
doecho "$i"
done

shell中的大括号用处挺多的,但这里的大括号表示生成一系列可能的集合,即1,2,3,4。另外,在也可借助双引号的能力来像C语言那样实现从1到4的遍历。

for((i=1; i<=4; i++));
doecho "$i"
done

5.3、while循环

#! /bin/bashcounter=0
while [ "$counter" -le 5 ]
doecho "Counter: $counter"((counter++))
done

counter++外面必须包裹两个小括号,因为双括号用于逻辑运算和数学操作。

5.4、case语句

fruit="apple"case "$fruit" in"apple")echo "You chose an apple.";;"banana")echo "You chose a banana.";;"orange"|"grape")echo "You chose an orange or a grape.";;*)echo "You chose something else.";;
esac

其中,“ * ) ”表示默认。在这里指如果fruit不是apple, banana, orange, grape其中一个就执行 “ * ) ”之后的操作。

6、函数定义

shell中的函数定义就比较奇怪了,主要体现在参数传输这一块。我们可以直接看看代码。

#! /bin/bashfunction name()
{name="$1"age="$2"echo "his name is $name"echo "his age is $age"
}name "xaioming" "18"

可以看到,上述例程所定义的函数之前有一个function的关键字,但其实这个是可有可无的。其次,可以用"$1"之类的符号来获得传入的参数。另外,即便调用该函数的时候传入了两个参数,但只拿除一个来用也无所谓。

#! /bin/bashname()
{name="$1"#age="$2"echo "his name is $name"#echo "his age is $age"
}name "xaioming" "18"

还有几点需要注意的,其一就是shell脚本和python一样,调用该函数必须在该函数定义之后。其二,在函数里面定义的变量如何不用local声明,那么是会被认为是全局变量的,这样可能会照成很多麻烦。

7、多脚本链接

前面提到shell脚本的编写逻辑和python有点像,调用函数之前必须在先定义函数。那么当定义的函数多了,就势必导致代码变成非常混乱和难读,这时候就需要学会多脚本链接了。
在一个名为script_1.sh的脚本写一个函数:

#! /bin/bashfunction hello()
{name="$1"echo "hello, i am $name"
}

在一个名为script_2.sh的脚本调用hello函数,并且传入名字:

#! /bin/bashsource ./script_1.shhello "li hua"

当你在script_2.sh中执行source script_1.sh这句代码的时候,它会引入script_1.sh的文件的代码并执行它。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/192880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

独孤思维:工资加了1000,却被骂懦弱无能

凡是为了工作镀金学历的人&#xff0c;都是为了逃避社会&#xff0c;都是懦弱无能的表现。 昨天有个读者跑来跟我说&#xff0c;本科毕业入职了一家直播公司做场控&#xff0c;结果做了一段时间发现这玩意就算是个高中生都会做。 太没意思了。 所以&#xff0c;决定辞职&…

C-语言每日刷题

目录 [蓝桥杯 2015 省 A] 饮料换购 题目描述 输入格式 输出格式 输入输出样例 # [蓝桥杯 2023 省 A] 平方差 题目描述 输入格式 输出格式 输入输出样例 说明/提示 【样例说明】 [NOIP2001 普及组] 数的计算 题目描述 输入格式 输出格式 输入输出样例 说明/提示 样例 1 解释 数据…

1.1.2.列表标签

一.无序列表 1.格式 ul 是Unordered List(无序列表)的缩写。列表里的项目用 <li> 标签记述。 <ul type"square"><li>1</li><li>2</li><li>3</li> </ul> 2.type属性 Disc是ul中type属性的默认值&#xff0…

【C++】多线程(二):std::mutex std::atomic的使用

这篇文章接着上一篇&#xff0c;继续介绍C中的多线程。 推荐先阅读上一篇 【C】多线程&#xff08;一&#xff09;&#xff1a;std::thread的使用 互斥 我们前面的函数&#xff0c;无论是线程之间&#xff0c;还是线程和主线程之间&#xff0c;都是没有数据交换的。 接下来让…

RK3568平台开发系列讲解(Linux系统篇)netlink 监听广播信息

** 🚀返回专栏总目录 文章目录 一、什么是netlink 机制二、netlink 的使用2.1、创建 socket2.2、绑定套接字2.3、接收数据沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍如何通过 netlink 监听广播信息。 一、什么是netlink 机制 Netlink 是 Linux 内核中…

企业计算机服务器locked1勒索病毒数据恢复,locked1勒索病毒解密流程

随着计算机技术的不断发展&#xff0c;越来越多的企业走向数字化办公时代&#xff0c;计算机技术为企业的生产运营提供了有利条件&#xff0c;但也为企业带来了网络安全威胁。在本月&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的速达办公软件遭到了lo…

zemax之初级像差理论与像差校正——像散

1.像散的概念 像散是指轴外物点发出的锥形光束通过光学系统聚焦后&#xff0c;光斑在像面上子午方向与弧矢方向的不一致性。轴外视场光束通过光瞳后&#xff0c;在子午方向与弧矢的光程不相等&#xff0c;造成两个方向光斑分离所形成的弥散斑&#xff0c;称为光学系统的像散。…

LeetCode二分查找:x 的平方根

LeetCode二分查找&#xff1a;x 的平方根 题目描述 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 **注意&#xff1a;**不允许使用任何内置指数函数和算符&#x…

js中setinterval怎么用?怎么才能让setinterval停下来?

setinterval()是定时调用的函数&#xff0c;可按照指定的周期&#xff08;以毫秒计&#xff09;来调用函数或计算表达式。 setinterval()的作用是在播放动画的时&#xff0c;每隔一定时间就调用函数&#xff0c;方法或对象。 setInterval() 方法会不停地调用函数&#xff0c;…

Leetcode刷题详解——乘积最大子数组

1. 题目链接&#xff1a;152. 乘积最大子数组 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续子数组&#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位…

安全SCDN对网站蜘蛛抓取有影响吗,使用SCDN对百度蜘蛛抓取有否好处

目前网站使用德迅云安全SCDN情况非常普遍&#xff0c;但也有些客户是第一次了解使用SCDN&#xff0c;会有担心一个百度蜘蛛抓取问题&#xff0c;担心使用了SCDN之后会影响百度蜘蛛抓取。其实是完全不必担心这个的&#xff0c;从理论上来讲&#xff0c;使用了SCDN并不会影响百度…

【Collection - LinkedList源码解析】

本文主要对Collection - LinkedList进行源码解析。 Collection - LinkedList源码解析 概述LinkedList实现 底层数据结构构造函数getFirst(), getLast()removeFirst(), removeLast(), remove(e), remove(index)add()addAll()clear()Positional Access 方法查找操作Queue 方法Deq…

【大学英语视听说上】Mid-term Test 2

Section A 【短篇新闻1】 You probably think college students are experts at sleeping, but parties, preparations for tests, personal problems and general stress can rack a students sleep habits, which can be bad for the body and the mind. Texas Tech Univer…

JavaWeb(一)

一、Javaweb介绍 Web&#xff1a;全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏览器访问的网站。 JavaWeb&#xff1a;使用Java技术进行web互联网开发。 总结: 1、JavaWeb就是使用Java技术进行web互联网开发 2、一个web项目包含三个部分&#xff0c;分别…

【论文阅读】-使用小波变换进行数字图像模糊检测

使用小波变换进行数字图像模糊检测 文章目录 使用小波变换进行数字图像模糊检测1、论文提出的背景2、论文提出的模糊检测方案2.1 不同边缘的模糊效果2.2 边缘类型和锐度检测2.3 方案实现步骤3、论文方案Python实现4、实验结果及总结本文将详细介绍 Hanghang Tong 、Mingjing Li…

分页助手入门以及小bug,报sql语法错误

导入坐标 5版本以上的分页助手 可以不用手动指定数据库语言&#xff0c;它会自动识别 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency&g…

(C语言)逆序输出字符串

#include<stdio.h> #include<string.h> int main() {int i;char s[100];scanf("%s",&s);int count strlen(s);for(int i count -1;i > 0; i --)printf("%c",s[i]);return 0;} 代码运行截图&#xff1a; 注&#xff1a;侵权可删

10个高级技巧提升你的Python代码Level!!!(建议收藏)

Python是一种功能强大且广泛应用于各个领域的编程语言。无论你是初学者还是有一定经验的开发者&#xff0c;掌握一些高级技巧可以大大提升你的Python编程能力&#xff0c;使你的代码更加高效、可靠和易于维护。本文将介绍10个提升Python编程技能的高级技巧&#xff0c;帮助你在…

五子棋AI算法自动测试方法

先前发了几篇五子棋游戏程序设计的博文&#xff0c;设计了游戏程序&#xff0c;也设计了AI智能奕棋的算法&#xff0c;运行程序检测算法的可行性&#xff0c;完成人机模式游戏功能的设置。 本文主要介绍自动测试算法的方法。 AI智能奕棋的算法testAIq( )&#xff0c;主要是检测…

前端项目打包和自动化部署(jenkins+gitee+nginx)

项目打包和自动化部署 一. 项目部署和DevOps 1. 传统的开发模式 在传统的开发模式中&#xff0c;开发的整个过程是按部就班就行&#xff1a; 但是这种模式存在很大的弊端&#xff1a; 工作的不协调&#xff1a;开发人员在开发阶段&#xff0c;测试和运维人员其实是处于等待…