百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Linux进阶bash笔记——开始使用 Bash

bigegpt 2025-01-26 21:15 9 浏览

1: Hello World

交互式 shell

Bash shell 常用于交互式使用: 它允许你输入和编辑命令,然后在按回车键时执行这些命令。许多基于 Unix 和类 Unix 的操作系统都将 Bash 作为默认 shell(尤其是 Linux 和 macOS)。终端启动时会自动进入交互式 Bash shell 进程。

输入以下内容,输出 Hello World:

echo "Hello World"
#> Hello World # 例子的输出结果

备注

只需在终端中输入 shell 的名称,即可更改 shell。例如:sh、bash 等。

echo 是 Bash 的内置命令,它会将收到的参数写入标准输出。默认情况下,它会在输出中加上换行符。

非交互式 shell

Bash shell 也可以通过脚本实现非交互式运行,这样就不需要人在终端前面交互从而实现一些定时任务等操作。交互行为和脚本行为应该是一致的,这是 Unix V7 Bourne shell 和 Bash 的重要设计考虑因素。因此,任何可以在命令行完成的操作都可以放在脚本文件中重复使用。

请按照以下步骤创建 Hello World 脚本:

1 创建一个名为 hello-world.sh 的新文件

touch hello-world.sh

2 运行以下命令使脚本可执行

chmod +x hello-world.sh

3 在文章中添加下面的代码:

#!/bin/bash

echo "Hello World"

第 1 行: 脚本的第一行必须以字符串 #! 开头,称为 shebang(中文Linux社区译名是“释伴”)。Shebang 命令操作系统运行 /bin/bash,即 Bash shell,并将脚本的路径作为参数传递给它。

例如: /bin/bash hello-world.sh

第 2 行: 使用 echo 命令将 Hello World 写入标准输出。

4 使用以下命令之一从命令行执行 hello-world.sh 脚本:

  • ./hello-world.sh - 最常用,推荐使用
  • /bin/bash hello-world.sh
  • bash hello-world.sh – 假设 /bin 已经在你的 $PATH 中(默认 /bin/usr/bin 有在 $PATH 中)
  • sh hello-world.sh

在实际生产使用中,你可以省略 .sh 扩展名(无论如何这都是误导,因为这是一个 Bash 脚本,而不是 sh 脚本),或许可以将文件移动到你 $PATH 中的目录里面,这样你可以就像使用 catls 等系统命令一样,无论你当前在什么工作目录都直接使用而不用加结对路径。

常见错误包括:

1 忘记对文件赋予执行权限,即 chmod +x hello-world.sh,导致执行命令时输出 ./hello-world.sh: Permission denied 权限被拒绝。

2 在 Windows 上编辑脚本,会产生 Bash 无法处理的错误行结束符。

常见的症状是:“command not found”(未找到命令),其中回车将光标强制移到行首,覆盖了错误信息中冒号前的文本。

可以使用dos2unix 程序修改脚本。如: dos2unix hello-world.shdos2unix 会对文件进行内联编辑。

3 使用 sh ./hello-world.sh 执行脚本,没有意识到 bash 和 sh 是不同的 shell,具有不同的功能(不过由于 Bash 是向后兼容的,所以相反的错误是无害的)。

总之,在每个脚本的文件名前明确写上 bash 或 sh(或 python 或 perl 或 awk 或 ruby 或......)比直接依赖脚本的 shebang 行要好得多。

为了让你的脚本更易于移植,一个常用的 Shebang 行是使用 #!/usr/bin/env bash 而不是硬编码 Bash 的路径。这样,/usr/bin/env 必须存在,但除此之外,bash 只需要在你的 PATH 中即可。在许多系统中,/bin/bash并不存在,你应该使用/usr/local/bin/bash或其他绝对路径;这一改动避免了找出其中的细节。

2: 使用变量的 Hello World

新建一个名为 hello.sh 的文件,内容如下,并使用 chmod +x hello.sh 赋予其可执行权限。

通过 ./hello.sh World运行脚本。

#!/usr/bin/env bash

# Note that spaces cannot be used around the `=` assignment operator
whom_variable="World"

# Use printf to safely output the data
printf "Hello, %s\n" "$whom_variable"
#> Hello, World

执行后将在标准输出中打印 Hello, World。

要告诉 bash 解释器你的脚本在哪里,你需要非常明确地将它指向包含脚本的目录,如果它是你当前的工作目录,通常使用 ./,其中 . 是当前目录的别名。如果没有指定目录,bash 解释器会尝试在环境变量 $PATH 所包含的目录中找到脚本。

下面的代码接受参数 $1(即第一个命令行参数),并以格式化的字符串输出,如下所示:Hello,.

通过 ./hello.sh World运行脚本。

#!/usr/bin/env bash
printf "Hello, %s\n" "$1"
#> Hello, World

It is important to note that $1 has to be quoted in double quote, not single quote. "$1" expands to the first command line argument, as desired, while '$1' evaluates to literal string $1.

需要注意的是,$1 必须使用双引号,而不是单引号。"$1"会按要求展开为第一个命令行参数,而 '$1' 会求值为字面字符串 $1

了解将变量文本置于双引号中的重要性。可以阅读这篇官方文档
https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells

3: 带用户输入的 Hello World

下面的程序将提示用户输入内容,然后将输入内容以字符串(文本)形式存储在一个变量中。然后使用该变量向用户发送一条信息。

#!/usr/bin/env bash
echo "Who are you?"
read name
echo "Hello, $name."

这里的读取命令是从标准输入中读取一行数据到变量名中。然后使用 $name 进行引用,并使用 echo 打印到标准输出。

输出示例

$ ./hello_world.sh
Who are you?
Matt
Hello, Matt.

在这里,用户输入了名字 "Matt",这段代码用来表示 “你好,Matt......”。

如果要在打印变量值时附加一些内容,请在变量名周围使用大括号,如下例所示:

#!/usr/bin/env bash
echo "What are you doing?"
read action
echo "You are ${action}ing."

示例输出:

$ ./hello_world.sh
What are you doing?
Sleep
You are Sleeping.

在这里,当用户输入一个操作时,“ing ”会在打印时附加到该操作上。

4: 引号在字符串中的重要性

引号对于 bash 中的字符串扩展非常重要。有了引号,你就可以控制 bash 如何解析和扩展字符串。

引号的使用有两种类型:

  • 弱引用:使用双引号:
  • 强引用:使用单引号: '

如果你想让 bash 引用你的参数变量,你可以使用弱引用

#!/usr/bin/env bash
world="World"
echo "Hello $world"
#> Hello World

如果你不想 bash 引用的的参数变量,而只是使用字符串本身,你可以使用强引用

#!/usr/bin/env bash
world="World"
echo 'Hello $world'
#> Hello $world

您也可以使用转义来防止扩展:

#!/usr/bin/env bash
world="World"
echo "Hello \$world"
#> Hello $world

5: 查看 Bash 内置项的信息

help 

上面的这个命令这将显示指定内置程序的 Bash 帮助(手册)页面。

例如,help unset 将显示

unset: unset [-f] [-v] [-n] [名称 ...]
    取消设定 shell 变量和函数的值和属性。
    
    对每一个 NAME 名称,删除对应的变量或函数。
    
    选项:
      -f        将每个 NAME 视为函数
      -v        将每个 NAME 视为变量
      -n        将每个 NAME 视为名称引用,只取消其本身而非其指向的变量
    
    不带选项时,unset 首先尝试取消设定一个变量,如果失败,再尝试取消设定一个函数。
    
    某些变量不可以被取消设定;参见 `readonly'。
    
    退出状态:
    返回成功,除非使用了无效的选项或者 NAME 名称为只读。

要查看附有简短说明的所有内置程序列表,请使用 help -d

[root@almalinux ~]# help -d
GNU bash,版本 5.1.8(1)-release (x86_64-redhat-linux-gnu)
这些 shell 命令是内部定义的。请输入 `help' 以获取一个列表。
输入 `help 名称' 以得到有关函数`名称'的更多信息。
使用 `info bash' 来获得关于 shell 的更多一般性信息。
使用 `man -k' 或 `info' 来获取不在列表中的命令的更多信息。

名称旁边的星号(*)表示该命令被禁用。

 job_spec [&]                                       history [-c] [-d 偏移量] [n] 或 history -anrw >
 (( 表达式 ))                                       if 命令; then 命令; [ elif 命令; then 命令; ]..>
 . 文件名 [参数]                                    jobs [-lnprs] [任务声明 ...] 或 jobs -x 命令 >
 :                                                  kill [-s 信号声明 | -n 信号编号 | -信号声明] >
 [ 参数... ]                                        let 参数 [参数 ...]
 [[ 表达式 ]]                                       local [option] 名称[=值] ...
 alias [-p] [名称[=值] ... ]                        logout [n]
 bg [任务声明 ...]                                  mapfile [-d 分隔符] [-n 计数] [-O 起始序号] [->
 bind [-lpvsPSVX] [-m 键映射] [-f 文件名] [-q 名>  popd [-n] [+N | -N]
 break [n]                                          printf [-v var] 格式 [参数]
 builtin [shell 内建 [参数 ...]]                    pushd [-n] [+N | -N | 目录]
 caller [表达式]                                    pwd [-LP]
 case 词 in [模式 [| 模式]...) 命令 ;;]... esac     read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文>
 cd [-L|[-P [-e]] [-@]] [目录]                      readarray [-d 定界符] [-n 计数] [-O 起始序号] [>
 command [-pVv] 命令 [参数 ...]                     readonly [-aAf] [名称[=值] ...] 或 readonly -p
 compgen [-abcdefgjksuv] [-o option] [-A action] >  return [n]
 complete [-abcdefgjksuv] [-pr] [-DEI] [-o option>  select NAME [in 词语 ... ;] do 命令; done
 compopt [-o|+o 选项] [-DEI] [名称 ...]             set [--abefhkmnptuvxBCHP] [-o 选项名] [--] [参>
 continue [n]                                       shift [n]
 coproc [名称] 命令 [重定向]                        shopt [-pqsu] [-o] [选项名 ...]
 declare [-aAfFgiIlnrtux] [-p] [name[=value] ...>   source 文件名 [参数]
 dirs [-clpv] [+N] [-N]                             suspend [-f]
 disown [-h] [-ar] [任务声明 ... | pid ...]         test [表达式]
 echo [-neE] [参数 ...]                             time [-p] 管道
 enable [-a] [-dnps] [-f 文件名] [名称 ...]         times
 eval [参数 ...]                                    trap [-lp] [[参数] 信号声明 ...]
 exec [-cl] [-a name] [command [argument ...]] [r>  true
 exit [n]                                           type [-afptP] 名称 [名称 ...]
 export [-fn] [名称[=值] ...] 或 export -p          typeset [-aAfFgiIlnrtux] [-p] name[=value] ...
 false                                              ulimit [-SHabcdefiklmnpqrstuvxPT] [限制]
 fc [-e 编辑器名] [-lnr] [起始] [终结] 或 fc -s >   umask [-p] [-S] [模式]
 fg [任务声明]                                      unalias [-a] 名称 [名称 ...]
 for 名称 [in 词语 ... ] ; do 命令; done            unset [-f] [-v] [-n] [名称 ...]
 for (( 表达式1; 表达式2; 表达式3 )); do 命令; do>  until 命令; do 命令; done
 function 名称 { 命令 ; } 或 name () { 命令 ; }     variables - 一些 shell 变量的名称和含义
 getopts optstring name [arg ...]                   wait [-fn] [-p var] [id ...]
 hash [-lr] [-p 路径名] [-dt] [名称 ...]            while 命令; do 命令; done
 help [-dms] [模式 ...]                             { 命令 ; }

6: 调试模式中的 Hello World

$ cat hello.sh
#!/bin/bash
echo "Hello World"
$ bash -x hello.sh
+ echo Hello World
Hello World

使用 -x 参数可以查看脚本中的每一行。下面就是一个很好的例子:

$ cat hello.sh
#!/bin/bash
echo "Hello World\n"
adding_string_to_number="s"
v=$(expr 5 + $adding_string_to_number)

$ ./hello.sh
Hello World

expr: non-integer argument

以上提示的错误不足以追踪脚本;但使用以下方法可以更好地了解在脚本中查找错误的位置。

$ bash -x hello.sh
+ echo Hello World\n
Hello World

+ adding_string_to_number=s
+ expr 5 + s
expr: non-integer argument
+ v=

7: 处理参数命名

#!/bin/bash

deploy=false
uglify=false

while (( $# > 1 )); do case $1 in
    --deploy) deploy="$2";;
    --uglify) uglify="$2";;
    *) break;
  esac; shift 2
done

$deploy && echo "will deploy... deploy = $deploy"
$uglify && echo "will uglify... uglify = $uglify"

# how to run
# chmod +x script.sh
# ./script.sh --deploy true --uglify false

如果您对我的文章有兴趣,我把我发布的文章都归档到我私人网站中去,欢迎访问 Corner 三的小角落 -- 首页 查阅之前的文章。

相关推荐

【Docker 新手入门指南】第十章:Dockerfile

Dockerfile是Docker镜像构建的核心配置文件,通过预定义的指令集实现镜像的自动化构建。以下从核心概念、指令详解、最佳实践三方面展开说明,帮助你系统掌握Dockerfile的使用逻...

Windows下最简单的ESP8266_ROTS_ESP-IDF环境搭建与腾讯云SDK编译

前言其实也没啥可说的,只是我感觉ESP-IDF对新手来说很不友好,很容易踩坑,尤其是对业余DIY爱好者搭建环境非常困难,即使有官方文档,或者网上的其他文档,但是还是很容易踩坑,多研究,记住两点就行了,...

python虚拟环境迁移(python虚拟环境conda)

主机A的虚拟环境向主机B迁移。前提条件:主机A和主机B已经安装了virtualenv1.主机A操作如下虚拟环境目录:venv进入虚拟环境:sourcevenv/bin/active(1)记录虚拟环...

Python爬虫进阶教程(二):线程、协程

简介线程线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能...

基于网络安全的Docker逃逸(docker)

如何判断当前机器是否为Docker容器环境Metasploit中的checkcontainer模块、(判断是否为虚拟机,checkvm模块)搭配学习教程1.检查根目录下是否存在.dockerenv文...

Python编程语言被纳入浙江高考,小学生都开始学了

今年9月份开始的新学期,浙江省三到九年级信息技术课将同步替换新教材。其中,新初二将新增Python编程课程内容。新高一信息技术编程语言由VB替换为Python,大数据、人工智能、程序设计与算法按照教材...

CentOS 7下安装Python 3.10的完整过程

1.安装相应的编译工具yum-ygroupinstall"Developmenttools"yum-yinstallzlib-develbzip2-develope...

如何在Ubuntu 20.04上部署Odoo 14

Odoo是世界上最受欢迎的多合一商务软件。它提供了一系列业务应用程序,包括CRM,网站,电子商务,计费,会计,制造,仓库,项目管理,库存等等,所有这些都无缝集成在一起。Odoo可以通过几种不同的方式进...

Ubuntu 系统安装 PyTorch 全流程指南

当前环境:Ubuntu22.04,显卡为GeForceRTX3080Ti1、下载显卡驱动驱动网站:https://www.nvidia.com/en-us/drivers/根据自己的显卡型号和...

spark+python环境搭建(python 环境搭建)

最近项目需要用到spark大数据相关技术,周末有空spark环境搭起来...目标spark,python运行环境部署在linux服务器个人通过vscode开发通过远程python解释器执行代码准备...

centos7.9安装最新python-3.11.1(centos安装python环境)

centos7.9安装最新python-3.11.1centos7.9默认安装的是python-2.7.5版本,安全扫描时会有很多漏洞,比如:Python命令注入漏洞(CVE-2015-2010...

Linux系统下,五大步骤安装Python

一、下载Python包网上教程大多是通过官方地址进行下载Python的,但由于国内网络环境问题,会导致下载很慢,所以这里建议通过国内镜像进行下载例如:淘宝镜像http://npm.taobao.or...

centos7上安装python3(centos7安装python3.7.2一键脚本)

centos7上默认安装的是python2,要使用python3则需要自行下载源码编译安装。1.安装依赖yum-ygroupinstall"Developmenttools"...

利用本地数据通过微调方式训练 本地DeepSeek-R1 蒸馏模型

网络上相应的教程基本都基于LLaMA-Factory进行,本文章主要顺着相应的教程一步步实现大模型的微调和训练。训练环境:可自行定义,mac、linux或者window之类的均可以,本文以ma...

【法器篇】天啦噜,库崩了没备份(天啦噜是什么意思?)

背景数据库没有做备份,一天突然由于断电或其他原因导致无法启动了,且设置了innodb_force_recovery=6都无法启动,里面的数据怎么才能恢复出来?本例采用解析建表语句+表空间传输的方式进行...