当前位置: 首页 > news >正文

Linux shell编程学习笔记14:编写和运行第一个shell脚本hello world!

 * 20231020 写这篇博文断断续续花了好几天,为了说明不同shell在执行同一脚本文件时的差别,我分别在csdn提供线上Linux环境 (使用的shell是zsh)和自己的电脑上(使用的shell是bash)做测试。功夫不负有心人,在其中一些实例中可以体现出zsh和bash的对脚本文件支持的差别,收获匪浅……

一、第一个shell脚本:hello world!

前面我们陆续介绍了与Linux shell编程有关的数据类型、数据运算、流程控制语句等基础知识,今天我们正式开始写shell脚本了。

我们学习某种编程语言,通常写的第一个程序就是输出hello world!,今天我们就编写和运行第一个shell脚本写的hello world!,假定脚本文件名为hello.sh。

二、 录入脚本文件hello.sh

脚本文件本质上是一个文本文件,我们有很多种方法可以来创建它,比如可以用vi或vim之类的文本编辑器,这类编辑器,对于用过DOS下编辑器的用户来说,上手起来比较容易,而对于只有windows使用经历的用户而言,刚开始用起来未必顺手。

所以我们这里直接在命令行来创建。

(一)使用 echo 命令 和 输出重定向 来创建脚本文件hello.sh

具体命令如下:

1.在zsh中测试

# csdn @ edu in ~ [20:28:14] 
$ echo "#! /bin/bash" > hello.sh

# csdn @ edu in ~ [20:31:32] 
$ echo 'echo "My first shell script file:Hello world!"' >> hello.sh

# csdn @ edu in ~ [20:32:28] 
$ echo "# My first shell script file ends." >> hello.sh

# csdn @ edu in ~ [20:32:53] 

 2.在bash中测试

user @ host : ~ $ echo '#! /bin/bash' > hello.sh

user @ host : ~ $ echo 'echo "My first shell script file:Hello world"' >> hello.sh
user @ host : ~ $ echo '# My first shell script file ends.' >> hello.sh

3.需要注意的地方

使用这种方法创建脚本文件时,有一点不方便的地方是需要注意双引号和单引号的使用,有时需要使用转义符。

(二)使用cp命令 和 /dev/stdin 来创建脚本文件hello.sh

我们也可以使用命令 :

cp /dev/stdin hello.sh

来录入hello.sh的内容。/dev/stdin 是Linux 系统中一个特殊的符号链接文件,指向当前进程的标准输入文件描述符,代表标准输入,比如键盘。

在输完所有shell脚本内容后,我们按Ctrl+Z键来结束。

但是用这种方法创建的脚本文件在执行时通常会遇到问题:

1.在zsh中测试

# csdn @ edu in ~ [23:11:12] 
$ cp /dev/stdin hello.sh
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.
^Z
[1]  + 148 suspended  cp /dev/stdin hello.sh

# csdn @ edu in ~ [23:12:26] C:20

# csdn @ edu in ~ [12:33:07] C:127
$ ./hello.sh
zsh: text file busy: ./hello.sh

2.在bash中测试 

 user @ host : ~ $ cp /dev/stdin hello.sh
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.
^Z
[1]+  已停止               cp /dev/stdin hello.sh

user @ host : ~ $ ./hello.sh 
bash: ./hello.sh: /bin/bash: 解释器错误: 文本文件忙

这是因为cp命令执行后,对应的进程并没结束,hello.sh仍处于被cp进程打开操作的状态。

解决的方法我们以后会介绍。

二、查看脚本文件hello.sh的内容

要查看脚本文件hello.sh的内容,方法同样有很多种。

(一)使用cat命令查看

我们可以使用命令

cat hello.sh

来查看刚才输入的hello.sh 的内容:

1.在zsh中测试

# csdn @ edu in ~ [23:12:26] C:20
$ cat hello.sh
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.

# csdn @ edu in ~ [23:12:36] 

2.在bash中测试

user @ host : ~ $ cat hello.sh
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.
user @ host : ~ $ 

 

 (二)使用cp命令 和 /dev/stdout来查看

 /dev/stdout 是Linux 系统中一个特殊的符号链接文件,指向当前进程的标准输出文件描述符,代表标准输出,比如显示器屏幕。

1.在zsh中测试

# csdn @ edu in ~ [21:11:30] 
$ cp hello.sh /dev/stdout
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.

# csdn @ edu in ~ [21:11:46] 

2.在bash中测试

user @ host : ~ $ cp hello.sh /dev/stdout
#! /bin/bash
echo "My first shell script file:Hello world"
# My first shell script file ends.
user @ host : ~ $ 

三、shell脚本解说

在上面的hello.sh中,共有三行:

#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.

我们逐行说明。

(一)第一行:shebang或hashbang语句:指定脚本解释器

第一行是

#! /bin/bash

1.shebang或hashbang语句的作用

以#! 开头,通常称为shebang或hashbang,用于指定默认情况下运行指定脚本的解释器路径,在上面的实例中我们指定的解释器是 /bin/bash。

这一行并不是必须的。如果一个脚本没有添加 shebang 行来指定解释器路径,则默认情况下系统会使用默认的 shell 来执行脚本。默认shell可以使用echo $0 或 echo $SHELL 查看。

由于目前可以在Linux系统上运行的shell有许多种:sh、bash、cshell、tcsh、zsh……尽管这些shell大多具有共同的语法,但它们确实有不同的语法或不同选项的处理方式,因此,同一个shell脚本文件在不同的shell中运行时可能会产生不同的结果。为了确保脚本文件获得预期的效果,我们建议为脚本指定解释器。

常见的解释器类型有:

#!/bin/sh
#!/bin/bash
#!/usr/bin/perl
#!/usr/bin/tcl
#!/bin/sed -f
#!/usr/awk -f

其中最常用、也是最常见的是 #!/bin/bash。

2.shebang或hashbang语句名称的由来

在Unix行话中,用sharp或hash(有时是mesh)来称呼字符#,用bang称呼字符!,因而shebang或 hashbang合起来就代表了这两个字符。到linux中也传承了这一传统。

(二)第二行:命令或语句

echo "My first shell script file:Hello world!"

这一行是echo命令,用来显示字符串。在shell脚本文件中,除了第一行可能是shebang或hashbang语句外,接下来的语句可以是变是赋值命令,或者ls等命令,或者是if等流程控制语句。

(三)第三行:以#开头的注释

# My first shell script file ends.

在shell脚本文件中,除了第一行以#! 开头的shebang或hashbang语句外,其他行中以#开始的内容均被视为注释。

关于注释,有两点说明:

1.注释的两种写法

有两种写法。

一种写法是像hello.sh的第3行这样将注释写成一个独立的行。

另一种写法是将注释可以直接写在要注释的命令之后。比如:

echo "My first shell script file:Hello world!" # dispaly the string

其中 # dispaly the string 就是我们添加的注释。

2.一个脚本文件中可以有包含多个注释。

我们可以根据需要,在脚本文件中添加许多个注释,可以写在命令之后,也可以单独成行。

三、执行脚本文件hello.sh

通常来说,执行脚本文件有很多种方法 。我们先看看其中三种最常见的方法:

(一)shell解释器名称 脚本文件名

其实就是将脚本文件名作为命令参数传递给 shell解释器执行。

1.使用bash来执行

由于我们在hello.sh的shebang或hashbang语句中指定使用bash作为解释器,所以我们可以用命令

bash hello.sh

 来执行hello.sh

# csdn @ edu in ~ [23:12:36] 
$ bash hello.sh
My first shell script file:Hello world!

# csdn @ edu in ~ [23:17:46] 

2.使用sh来执行

我们也可以用命令

sh hello.sh

来执行:

# csdn @ edu in ~ [23:17:46] 
$ sh hello.sh
My first shell script file:Hello world!

# csdn @ edu in ~ [23:19:27] 

(二)脚本文件说明符

脚本文件说明符的格式是:

路径/脚本文件名

其中路径又分为绝对路径和相对路径。所以这种方式又可以细分为两种格式。

1.相对路径/脚本文件名

由于我们是在当前目录下创建了hello.sh,所以hello.sh的相对路径就是./,我们使用命令

./hello.sh

来运行看看。

(1)在zsh中测试

# csdn @ edu in ~ [12:27:14] C:127
$ ./hello.sh 
zsh: permission denied: ./hello.sh

看来是权限问题,我们使用ls -l命令查看 文件hello.sh的详细信息:

# csdn @ edu in ~ [12:29:22] C:126
$ ls -l hello.sh      
-rw------- 1 csdn csdn 95 10月 20 12:23 hello.sh

我们只有读(r)写(w)权限,还没有执行(x)权限,我们使用命令

chmod a+x hello.sh

增加执行权限。

# csdn @ edu in ~ [12:31:53] C:1
$ chmod a+x  hello.sh 

# csdn @ edu in ~ [12:32:53] 
$ ls -l hello.sh
-rwx--x--x 1 csdn csdn 95 10月 20 12:23 hello.sh

 这下有执行权限(x)了。再试试看:

# csdn @ edu in ~ [20:36:35] 
$ ./hello.sh        
My first shell script file:Hello world!

 (2)在bash中测试

user @ host : ~ $ ./hello.sh
bash: ./hello.sh: 权限不够
user @ host : ~ $ ls -l hello.sh
-rw--w---- 1 gxxc gxxc 94 10月 20 18:36 hello.sh
user @ host : ~ $ chmod +x hello.sh
user @ host : ~ $ ls -l hello.sh
-rwx-wx--x 1 gxxc gxxc 94 10月 20 18:36 hello.sh
user @ host : ~ $ ./hello.sh
My first shell script file:Hello world
user @ host : ~ $ 

2.绝对路径/脚本文件名

(1)在zsh中测试

我们先用pwd命令查看当前目录路径:

# csdn @ edu in ~ [20:36:40] 
$ pwd
/home/csdn

 可以看到,当前目录路径是/home/csdn,所以脚本文件的绝对路径文件说明符是/home/csdn/hello.sh。

那么我们可以通过命令:/home/csdn/hello.sh 来执行脚本:

# csdn @ edu in ~ [20:38:39] 
$ /home/csdn/hello.sh
My first shell script file:Hello world!

(2)在bash中测试

user @ host : ~ $ pwd
/tmp
user @ host : ~ $ /tmp/hello.sh
My first shell script file:Hello world
user @ host : ~ $ 

 在上面的例子中,当前目录的路径是/tmp,所以脚本文件的绝对路径文件说明符是/tmp/hello.sh。

所以我们可以通过命令:/tmp/hello.sh 来执行脚本。

(3)需要的注意地方

不管使用相对路径还是绝对路径来执行脚本文件,我们都要使用chmod 命令来为脚本文件增加执行(x)权限。

(三)利用source命令来执行。

有没有不用修改脚本文件权限又能执行脚本文件的方法呢?除了上面介绍的第一种方法:将脚本文件名作为命令参数传递给 shell解释器执行 外,我们还可以使用source命令来实现。

source 是 Shell 内置命令的一种,它会忽略脚本文件的权限,读取脚本文件,并依次执行其中的命令语句。

使用source命令执行脚本文件的格式是:

source 脚本文件说明符

也可以简写为:

. 脚本文件说明符

 注意:简写命令格式中. 和 脚本文件说明符之间要用空格分隔。

1.在zsh中测试

# csdn @ edu in ~ [20:38:50] 
$ source ./hello.sh
My first shell script file:Hello world!

# csdn @ edu in ~ [20:47:56] 
$ . ./hello.sh
My first shell script file:Hello world!

# csdn @ edu in ~ [20:48:25] 
$ source hello.sh  
My first shell script file:Hello world!

# csdn @ edu in ~ [20:49:07] 
$ . hello.sh
.: no such file or directory: hello.sh

# csdn @ edu in ~ [20:49:15] C:127

可见,在zsh中,使用“source 脚本文件说明符”来执行脚本文件时,如果脚本文件在当前目录中,那么文件说明符中的路径可以省略。

使用“. 脚本文件说明符” 这种简写格式来执行脚本文件时,脚本文件说明符的路径不能少。

2.在bash中测试

user @ host : ~ $ source hello.sh
My first shell script file:Hello world
user @ host : ~ $ source ./hello.sh
My first shell script file:Hello world
user @ host : ~ $ . hello.sh
My first shell script file:Hello world
user @ host : ~ $ . ./hello.sh
My first shell script file:Hello world

  

可见,在bash中,不管使用“source 脚本文件说明符”还是“. 脚本文件说明符” 这种简写格式来执行脚本文件时,如果脚本文件在当前目前下,那么文件说明符中的路径都可以省略。

对比可见bash用起来更方便一些,bash能成为最流行的shell,这是其中的原因之一。

相关文章:

Linux shell编程学习笔记14:编写和运行第一个shell脚本hello world!

* 20231020 写这篇博文断断续续花了好几天,为了说明不同shell在执行同一脚本文件时的差别,我分别在csdn提供线上Linux环境 (使用的shell是zsh)和自己的电脑上(使用的shell是bash)做测试。功夫不负有心人&am…...

隐式类型转换

什么是隐式类型转换,多参数的造函数隐式类型转换,和单参数的构造函数隐式类型转换有什么区别 C中有三种主要的隐式类型转换: 1:多参数的构造函数隐式类型转换 2:单参数的构造函数隐式类型转换 3:成员函数隐式类型转换。…...

单例模式:饿汉式、懒汉式

一、单例模式 定义:一个类中的对象只能有一个,它在内存中只会创建一次对象的设计模式。 用法:在程序中如果多次用到同一个类中的方法进行操作时,在使用时就会创建多个对象。为了防止频繁创建对象造成内存资源浪费,就可…...

“人间烟火”背后,长沙招商引资再出圈

连续多年,长沙荣膺全国最具幸福感城市。同时,长沙也被誉为“中部崛起的引擎城市”。长沙不仅有网红城市的人间烟火气,更以创新的精神,优质的营商环境,高效的政府服务,丰富的人才资源和深厚的产业基础&#…...

操作系统【OS】中断和异常

异常(内中断) 中断(外中断) 基本概念 由CPU执行指令内部产生的事件内中断都是不可屏蔽中断,一旦出现,就要立即处理。 由来自CPU外部的设备发出的中断请求(常用于输入输出)典型的由…...

[AutoSAR系列] 1.1 AutoSar 发展历史

AUTOSAR,全称为Automotive Open System Architecture,即汽车开放系统架构。 AutoSar 是一项开源的汽车软件标准,旨在提高汽车电子系统的互操作性和可重用性。AutoSar 成员通常是汽车制造商、电子元件制造商、软件供应商和工具供应商等公司,他们在共同开发和推进 AutoSar 标…...

【vscode编辑器插件】前端 php unity自用插件分享

文章目录 一篇一句前言前端vuegitphpunity后端其他待续完结 一篇一句 “思考是最困难的工作,这也许是为什么很少有人这样做。” - 亨利福特(Henry Ford) 前言 无论是什么语言,我都会选择使用vscode进行开发,我愿称v…...

【企业级SpringBoot单体项目模板 】—— 项目代码管理

😜作 者:是江迪呀✒️本文关键词:SpringBoot项目模版、企业级、模版、代码管理☀️每日 一言:生命力顽强的种子,从不对瘠土唱诅咒的歌。 文章目录 一、第一种:先创建仓库1.1 创建仓库1.2 clone…...

Python读取Excel文件中指定的列数并生成CSV文件

0x00 安装Pandas和OpenPyXL pip install pandaspip install openpyxl0x01 Encoding import os import pandas as pd import openpyxl from openpyxl import load_workbook import csvdef write_dict_to_csv(dict_data, fileName):df pd.DataFrame.from_dict(dict_data)# 将D…...

MySQl有哪些索引(种类)?索引特点?为什么要使用索引?

普通索引:仅加速查询唯一索引:加速查询 列值唯一(可以有null)主键索引:加速查询 列值唯一(不可以有null) 表中只有一个组合索引:多列值组成一个索引,专门用于组合搜索&…...

49数码论坛系统设计与实现

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…...

蓝桥杯每日一题2023.10.19

题目描述 完全二叉树的权值 - 蓝桥云课 (lanqiao.cn) 题目分析 我们以每一个节点的坐标来将这一深度的权值之和相加从而算出权值和 要清楚每一个深度的其实节点和末尾节点,使用双指针将这个深度节点的权值和计算出来,记录所 需要的深度即可 #includ…...

NIO IN:技术蔚来的首次「大阅兵」

宝山,上海第一钢铁厂旧址。 上周,蔚来在这里点亮金色炉台,2500 立方米高炉,浓重的工业气质与古典凝重的光影交织,蔚来 NIO IN 用科技的进步呼应那个火红的年代。 这是蔚来第一次开科技发布会,为了全方位展…...

Android推送问题排查

针对MobPush智能推送服务在使用过程中可能出现的问题,本文为各位开发者们带来了针对MobPush安卓端推送问题的解决办法。 TCP在线推送排查 排查TCP在线收不到推送时,我们先通过客户端的RegistrationId接口获取设备的唯一标识 示例: MobPush…...

轻量级导出 Excel 标准格式

一般业务系统中都有导出到 Excel 功能,其实质就是把数据库里面一条条记录转换到 Excel 文件上。Java 常用的第三方类库有 Apache POI 和阿里巴巴开源的 EasyExcel 等。另外也有通过 Web 模板技术渲染 Excel 文件导出,这实质是 MVC 模式的延伸&#xff0c…...

蓝桥杯 (年号字串 C++)

思路&#xff1a; 1、看成10进制转化成26进制 。 2、A表示1、B表示2。以此类推&#xff0c;Z表示26. 代码&#xff1a; #include <iostream> using namespace std; int main() {char str[10]; int sum 2019, n, i 0; while (sum > 0) {str[i] sum % 26 64;sum / …...

软件测试01

一、认识软件及测试 1、什么是软件 控制计算机硬件工作的工具 2、软件的基本组成 页面客户端------请求----->代码服务器-------请求------>数据服务器 3、软件产生过程 需求产生------->需求文档------->设计效果图------->产品开发-------->产品测试 …...

【IBIS 模型与仿真 - IBISWriter and Write_IBIS】

本文将介绍如何从用户设计中编写自定义IBIS模型。 本文是 SelectIO 解决方案中心&#xff08;Xilinx 答复 50924&#xff09;的设计助手部分&#xff08;Xilinx 答复 50926&#xff09;的一部分。 原文链接&#xff1a;https://support.xilinx.com/s/article/50957?languagee…...

[题] 筛质数 #质数(素数)

题目 AcWing 868. 筛质数 题解 方法一&#xff1a;朴素筛法 及其优化&#xff1a;埃氏筛 从2~n枚举 i,再从小到大枚举所有已知的质数 primes[j],筛掉合数 i*primes[j],遇到新的质数就入队 枚举所有小于n的数i,将i的所有倍数筛掉。 筛完后剩下的数就是质数。 朴素做法 void ge…...

C进阶-语言文件操作

本章重点&#xff1a; 什么是文件 文件名 文件类型 文件缓冲区 文件指针 文件的打开和关闭文件的顺序读写文件的随机读写文件结束的判定 1. 什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件 1.1 程序文件…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...