热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux简单脚本fi报错,Shell脚本编程30分钟入门

什么是Shell脚本示例看个例子吧:#!binshcd~mkdirshell_tutcdshell_tutfor((i0;i

什么是Shell脚本

示例

看个例子吧:

#!/bin/sh

cd ~

mkdir shell_tut

cd shell_tut

for ((i&#61;0; i<10; i&#43;&#43;)); do

touch test_$i.txt

done

示例解释

第1行&#xff1a;指定脚本解释器&#xff0c;这里是用/bin/sh做解释器的

第2行&#xff1a;切换到当前用户的home目录

第3行&#xff1a;创建一个目录shell_tut

第4行&#xff1a;切换到shell_tut目录

第5行&#xff1a;循环条件&#xff0c;一共循环10次

第6行&#xff1a;创建一个test_1…10.txt文件

第7行&#xff1a;循环体结束

cd, mkdir, touch都是系统自带的程序&#xff0c;一般在/bin或者/usr/bin目录下。for, do, done是sh脚本语言的关键字。

shell和shell脚本的概念

shell是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。Ken Thompson的sh是第一种Unix Shell&#xff0c;Windows Explorer是一个典型的图形界面Shell。

shell脚本(shell script)&#xff0c;是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本&#xff0c;但读者朋友要知道&#xff0c;shell和shell script是两个不同的概念。由于习惯的原因&#xff0c;简洁起见&#xff0c;本文出现的“shell编程”都是指shell脚本编程&#xff0c;不是指开发shell自身(如Windows Explorer扩展开发)。

环境

shell编程跟java、php编程一样&#xff0c;只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

OS

当前主流的操作系统都支持shell编程&#xff0c;本文档所述的shell编程是指Linux下的shell&#xff0c;讲的基本都是POSIX标准下的功能&#xff0c;所以&#xff0c;也适用于Unix及BSD(如Mac OS)。

Linux

Linux默认安装就带了shell解释器。

Mac OS

Mac OS不仅带了sh、bash这两个最基础的解释器&#xff0c;还内置了ksh、csh、zsh等不常用的解释器。

Windows上的模拟器

windows出厂时没有内置shell解释器&#xff0c;需要自行安装&#xff0c;为了同时能用grep, awk, curl等工具&#xff0c;最好装一个cygwin或者mingw来模拟linux环境。

脚本解释器

sh

即Bourne shell&#xff0c;POSIX(Portable Operating System Interface)标准的shell解释器&#xff0c;它的二进制文件路径通常是/bin/sh&#xff0c;由Bell Labs开发。

本文讲的是sh&#xff0c;如果你使用其它语言用作shell编程&#xff0c;请自行参考相应语言的文档。

bash

Bash是Bourne shell的替代品&#xff0c;属GNU Project&#xff0c;二进制文件路径通常是/bin/bash。业界通常混用bash、sh、和shell&#xff0c;比如你会经常在招聘运维工程师的文案中见到&#xff1a;熟悉Linux Bash编程&#xff0c;精通Shell编程。

在CentOS里&#xff0c;/bin/sh是一个指向/bin/bash的符号链接:

[root&#64;centosraw ~]# ls -l /bin/*sh

-rwxr-xr-x. 1 root root 903272 Feb 22 05:09 /bin/bash

-rwxr-xr-x. 1 root root 106216 Oct 17 2012 /bin/dash

lrwxrwxrwx. 1 root root 4 Mar 22 10:22 /bin/sh -> bash

但在Mac OS上不是&#xff0c;/bin/sh和/bin/bash是两个不同的文件&#xff0c;尽管它们的大小只相差100字节左右:

iMac:~ wuxiao$ ls -l /bin/*sh

-r-xr-xr-x 1 root wheel 1371648 6 Nov 16:52 /bin/bash

-rwxr-xr-x 2 root wheel 772992 6 Nov 16:52 /bin/csh

-r-xr-xr-x 1 root wheel 2180736 6 Nov 16:52 /bin/ksh

-r-xr-xr-x 1 root wheel 1371712 6 Nov 16:52 /bin/sh

-rwxr-xr-x 2 root wheel 772992 6 Nov 16:52 /bin/tcsh

-rwxr-xr-x 1 root wheel 1103984 6 Nov 16:52 /bin/zsh

高级编程语言

理论上讲&#xff0c;只要一门语言提供了解释器(而不仅是编译器)&#xff0c;这门语言就可以胜任脚本编程&#xff0c;常见的解释型语言都是可以用作脚本编程的&#xff0c;如&#xff1a;Perl、Tcl、Python、PHP、Ruby。Perl是最老牌的脚本编程语言了&#xff0c;Python这些年也成了一些linux发行版的预置解释器。

编译型语言&#xff0c;只要有解释器&#xff0c;也可以用作脚本编程&#xff0c;如C shell是内置的(/bin/csh)&#xff0c;Java有第三方解释器Jshell&#xff0c;Ada有收费的解释器AdaScript。

如下是一个PHP Shell Script示例(假设文件名叫test.php)&#xff1a;

#!/usr/bin/php

for ($i&#61;0; $i <10; $i&#43;&#43;)

echo $i . "\n";

执行&#xff1a;

/usr/bin/php test.php

或者&#xff1a;

chmod &#43;x test.php

./test.php

如何选择shell编程语言

熟悉 vs 陌生

如果你已经掌握了一门编程语言(如PHP、Python、Java、Javascript)&#xff0c;建议你就直接使用这门语言编写脚本程序&#xff0c;虽然某些地方会有点啰嗦&#xff0c;但你能利用在这门语言领域里的经验(单元测试、单步调试、IDE、第三方类库)。

新增的学习成本很小&#xff0c;只要学会怎么使用shell解释器(Jshell、AdaScript)就可以了。

简单 vs 高级

如果你觉得自己熟悉的语言(如Java、C)写shell脚本实在太啰嗦&#xff0c;你只是想做一些备份文件、安装软件、下载数据之类的事情&#xff0c;学着使用sh&#xff0c;bash会是一个好主意。

shell只定义了一个非常简单的编程语言&#xff0c;所以&#xff0c;如果你的脚本程序复杂度较高&#xff0c;或者要操作的数据结构比较复杂&#xff0c;那么还是应该使用Python、Perl这样的脚本语言&#xff0c;或者是你本来就已经很擅长的高级语言。因为sh和bash在这方面很弱&#xff0c;比如说&#xff1a;

它的函数只能返回字串&#xff0c;无法返回数组

它不支持面向对象&#xff0c;你无法实现一些优雅的设计模式

它是解释型的&#xff0c;一边解释一边执行&#xff0c;连PHP那种预编译都不是&#xff0c;如果你的脚本包含错误(例如调用了不存在的函数)&#xff0c;只要没执行到这一行&#xff0c;就不会报错环境兼容性

如果你的脚本是提供给别的用户使用&#xff0c;使用sh或者bash&#xff0c;你的脚本将具有最好的环境兼容性&#xff0c;perl很早就是linux标配了&#xff0c;python这些年也成了一些linux发行版的标配&#xff0c;至于mac os&#xff0c;它默认安装了perl、python、ruby、php、java等主流编程语言。

第一个shell脚本

编写

打开文本编辑器&#xff0c;新建一个文件&#xff0c;扩展名为sh(sh代表shell)&#xff0c;扩展名并不影响脚本执行&#xff0c;见名知意就好&#xff0c;如果你用php写shell 脚本&#xff0c;扩展名就用php好了。

输入一些代码&#xff0c;第一行一般是这样&#xff1a;

#!/bin/bash

#!/usr/bin/php

“#!”是一个约定的标记&#xff0c;它告诉系统这个脚本需要什么解释器来执行。

运行

运行Shell脚本有两种方法&#xff1a;

作为可执行程序

chmod &#43;x test.sh

./test.sh

注意&#xff0c;一定要写成./test.sh&#xff0c;而不是test.sh&#xff0c;运行其它二进制的程序也一样&#xff0c;直接写test.sh&#xff0c;linux系统会去PATH里寻找有没有叫test.sh的&#xff0c;而只有/bin, /sbin, /usr/bin&#xff0c;/usr/sbin等在PATH里&#xff0c;你的当前目录通常不在PATH里&#xff0c;所以写成test.sh是会找不到命令的&#xff0c;要用./test.sh告诉系统说&#xff0c;就在当前目录找。

通过这种方式运行bash脚本&#xff0c;第一行一定要写对&#xff0c;好让系统查找到正确的解释器。

这里的"系统"&#xff0c;其实就是shell这个应用程序(想象一下Windows Explorer)&#xff0c;但我故意写成系统&#xff0c;是方便理解&#xff0c;既然这个系统就是指shell&#xff0c;那么一个使用/bin/sh作为解释器的脚本是不是可以省去第一行呢&#xff1f;是的。

作为解释器参数

这种运行方式是&#xff0c;直接运行解释器&#xff0c;其参数就是shell脚本的文件名&#xff0c;如&#xff1a;

/bin/sh test.sh

/bin/php test.php

这种方式运行的脚本&#xff0c;不需要在第一行指定解释器信息&#xff0c;写了也没用。

变量

定义变量

定义变量时&#xff0c;变量名不加美元符号($)&#xff0c;如&#xff1a;

your_name&#61;"qinjx"

注意&#xff0c;变量名和等号之间不能有空格&#xff0c;这可能和你熟悉的所有编程语言都不一样。

除了显式地直接赋值&#xff0c;还可以用语句给变量赋值&#xff0c;如&#xff1a;

for file in &#96;ls /etc&#96;

使用变量

使用一个定义过的变量&#xff0c;只要在变量名前面加美元符号即可&#xff0c;如&#xff1a;

your_name&#61;"qinjx"

echo $your_name

echo ${your_name}

变量名外面的花括号是可选的&#xff0c;加不加都行&#xff0c;加花括号是为了帮助解释器识别变量的边界&#xff0c;比如下面这种情况&#xff1a;

for skill in Ada Coffe Action Java do

echo "I am good at ${skill}Script"

done

如果不给skill变量加花括号&#xff0c;写成echo "I am good at $skillScript"&#xff0c;解释器就会把$skillScript当成一个变量(其值为空)&#xff0c;代码执行结果就不是我们期望的样子了。

推荐给所有变量加上花括号&#xff0c;这是个好的编程习惯。IntelliJ IDEA编写shell script时&#xff0c;IDE就会提示加花括号。

重定义变量

已定义的变量&#xff0c;可以被重新定义&#xff0c;如&#xff1a;

your_name&#61;"qinjx"

echo $your_name

your_name&#61;"alibaba"

echo $your_name

这样写是合法的&#xff0c;但注意&#xff0c;第二次赋值的时候不能写$your_name&#61;"alibaba"&#xff0c;使用变量的时候才加美元符。

注释

以“#”开头的行就是注释&#xff0c;会被解释器忽略。

多行注释

sh里没有多行注释&#xff0c;只能每一行加一个#号。就像这样&#xff1a;

#--------------------------------------------

# 这是一个自动打ipa的脚本&#xff0c;基于webfrogs的ipa-build书写&#xff1a;https://github.com/webfrogs/xcode_shell/blob/master/ipa-build

# 功能&#xff1a;自动为etao ios app打包&#xff0c;产出物为14个渠道的ipa包

# 特色&#xff1a;全自动打包&#xff0c;不需要输入任何参数

#--------------------------------------------

##### 用户配置区 开始 #####

#

#

# 项目根目录&#xff0c;推荐将此脚本放在项目的根目录&#xff0c;这里就不用改了

# 应用名&#xff0c;确保和Xcode里Product下的target_name.app名字一致

#

##### 用户配置区 结束 #####

如果在开发过程中&#xff0c;遇到大段的代码需要临时注释起来&#xff0c;过一会儿又取消注释&#xff0c;怎么办呢&#xff1f;每一行加个#符号太费力了&#xff0c;可以把这一段要注释的代码用一对花括号括起来&#xff0c;定义成一个函数&#xff0c;没有地方调用这个函数&#xff0c;这块代码就不会执行&#xff0c;达到了和注释一样的效果。

字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串&#xff0c;也没啥其它类型好用了&#xff0c;哈哈)&#xff0c;字符串可以用单引号&#xff0c;也可以用双引号&#xff0c;也可以不用引号。单双引号的区别跟PHP类似。

单引号

str&#61;&#39;this is a string&#39;

单引号字符串的限制&#xff1a;

单引号里的任何字符都会原样输出&#xff0c;单引号字符串中的变量是无效的

单引号字串中不能出现单引号(对单引号使用转义符后也不行)双引号

your_name&#61;&#39;qinjx&#39;

str&#61;"Hello, I know your are \"$your_name\"! \n"

双引号里可以有变量

双引号里可以出现转义字符字符串操作

拼接字符串

your_name&#61;"qinjx"

greeting&#61;"hello, "$your_name" !"

greeting_1&#61;"hello, ${your_name} !"

echo $greeting $greeting_1

获取字符串长度

string&#61;"abcd"

echo ${#string} #输出&#xff1a;4

提取子字符串

string&#61;"alibaba is a great company"

echo ${string:1:4} #输出&#xff1a;liba

查找子字符串

string&#61;"alibaba is a great company"

echo &#96;expr index "$string" is&#96;#输出&#xff1a;8&#xff0c;这个语句的意思是&#xff1a;找出单词is在这名话中的位置

更多

数组

管道

条件判断

流程控制

和Java、PHP等语言不一样&#xff0c;sh的流程控制不可为空&#xff0c;如&#xff1a;

if (isset($_GET["q"])) {

search(q);

}

else {

//do nothing

}

在sh/bash里可不能这么写&#xff0c;如果else分支没有语句执行&#xff0c;就不要写这个else。

还要注意&#xff0c;sh里的if [ $foo -eq 0 ]&#xff0c;这个方括号跟Java/PHP里if后面的圆括号大不相同&#xff0c;它是一个可执行程序(和cd, ls, grep一样)&#xff0c;相不到吧&#xff1f;在CentOS上&#xff0c;它在/usr/bin目录下&#xff1a;

ll /usr/bin/[

-rwxr-xr-x. 1 root root 33408 6月 22 2012 /usr/bin/[

正因为方括号在这里是一个可执行程序&#xff0c;方括号后面必须加空格&#xff0c;不能写成if [$foo -eq 0]

if else

if

if condition

then

command1

command2

...

commandN

fi

写成一行(适用于终端命令提示符)&#xff1a;

if &#96;ps -ef | grep ssh&#96;; then echo hello; fi

末尾的fi就是if倒过来拼写&#xff0c;后面还会遇到类似的

if else

if condition

then

command1

command2

...

commandN

else

command

fi

if else-if else

if condition1

then

command1

elif condition2

command2

else

commandN

fi

for while

for

在开篇的示例里演示过了&#xff1a;

for var in item1 item2 ... itemN

do

command1

command2

...

commandN

done

写成一行&#xff1a;

for var in item1 item2 ... itemN; do command1; command2… done;

C风格的for

for (( EXP1; EXP2; EXP3 ))

do

command1

command2

command3

done

while

while condition

do

command

done

无限循环

while :

do

command

done

或者

while true

do

command

done

或者

for (( ; ; ))

until

until condition

do

command

done

case

case "${opt}" in

"Install-Puppet-Server" )

install_master $1

exit

;;

"Install-Puppet-Client" )

install_client $1

exit

;;

"Config-Puppet-Server" )

config_puppet_master

exit

;;

"Config-Puppet-Client" )

config_puppet_client

exit

;;

"Exit" )

exit

;;

* ) echo "Bad option, please choose again"

esac

case的语法和C family语言差别很大&#xff0c;它需要一个esac(就是case反过来)作为结束标记&#xff0c;每个case分支用右圆括号&#xff0c;用两个分号表示break

函数

定义

调用

文件包含

可以使用source和.关键字&#xff0c;如&#xff1a;

source ./function.sh

. ./function.sh

在bash里&#xff0c;source和.是等效的&#xff0c;他们都是读入function.sh的内容并执行其内容(类似PHP里的include)&#xff0c;为了更好的可移植性&#xff0c;推荐使用第二种写法。

包含一个文件和在执行一个文件一样&#xff0c;也要写这个文件的路径&#xff0c;不能光写文件名&#xff0c;比如上述例子中:

. ./function.sh

不可以写作&#xff1a;

. function.sh

如果function.sh是用户传入的参数&#xff0c;如何获得它的绝对路径呢&#xff1f;方法是&#xff1a;

real_path&#61;&#96;readlink -f $1&#96;#$1是用户输入的参数&#xff0c;如function.sh

. $real_path

用户输入

执行脚本时传入

脚本运行中输入

select菜单

stdin和stdout

常用的命令

sh脚本结合系统命令便有了强大的威力&#xff0c;在字符处理领域&#xff0c;有grep、awk、sed三剑客&#xff0c;grep负责找出特定的行&#xff0c;awk能将行拆分成多个字段&#xff0c;sed则可以实现更新插入删除等写操作。

ps

查看进程列表

grep

排除grep自身

查找与target相邻的结果

awk

sed

插入

替换

删除

xargs

curl

综合案例

参考资料

相关课程

Tony老师讲

Shell语法基础&#xff1a;语言学习&#xff0c;语法先行&#xff01;变量和运算符的学习&#xff0c;让你在shell编程的道路上继续行进&#xff01;

Shell技能提升&#xff1a;基础语法与Linux的特性相结合&#xff0c;提升你的系统管理技能。

Shell实用案例&#xff1a;终于到最后一步啦&#xff01;流程控制语法与实用案例&#xff0c;小伙伴是不是收获颇多呢&#xff1f;



推荐阅读
  • 技术日志:Ansible的安装及模块管理详解 ... [详细]
  • awk if 包含_千面 awk | Linux 中国
    awk命令不仅提供了简单的输入字符串筛选功能,还包含提取数据列、打印简单文本、筛选内容——甚至做一些数学计算。--SandraHenry-stockerawk命令不仅 ... [详细]
  • 数字图书馆近期展出了一批精选的Linux经典著作,这些书籍虽然部分较为陈旧,但依然具有重要的参考价值。如需转载相关内容,请务必注明来源:小文论坛(http://www.xiaowenbbs.com)。 ... [详细]
  • 在开发过程中,我最初也依赖于功能全面但操作繁琐的集成开发环境(IDE),如Borland Delphi 和 Microsoft Visual Studio。然而,随着对高效开发的追求,我逐渐转向了更加轻量级和灵活的工具组合。通过 CLIfe,我构建了一个高度定制化的开发环境,不仅提高了代码编写效率,还简化了项目管理流程。这一配置结合了多种强大的命令行工具和插件,使我在日常开发中能够更加得心应手。 ... [详细]
  • 在Linux系统中,为了提高安全性,可以通过设置命令执行超时和用户超时注销来防止因用户长时间未操作而带来的安全隐患。具体而言,可以通过编辑 `/etc/profile` 文件,添加或修改相关参数,确保用户在指定时间内无操作后自动注销。此外,还可以利用 `timeout` 命令来限制特定命令的执行时间,进一步增强系统的稳定性和安全性。 ... [详细]
  • 10分钟带你搞定 Linux awk命令
    欢迎加入JackTian技术交流群!CSDN海量资源免费下载!简介awk是一个强大的文本分析工具,相对于grep的查找,se ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 在 `UITableViewController` 中采用简洁的平面样式布局时,可以通过优化代码实现单元格扩展至屏幕边缘的效果,同时确保节标题以分组样式呈现,从而提升用户体验和界面美观度。通过这种方式,可以更好地组织和展示列表内容,使其更加清晰和有序。 ... [详细]
  • MySQL 8.0 MGR 自动化部署与配置:DBA 和开源工具的高效解决方案
    MySQL 8.0 MGR 自动化部署与配置:DBA 和开源工具的高效解决方案 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • Linux Shell变量初探:初始值解析与使用指南
    本文探讨了Linux Shell中变量的基本概念及其在BASH中的应用。变量是用于存储可变数据的标识符,能够代表不同的值。文章详细介绍了BASH shell的主要优势,包括强大的命令编辑能力、自动补全功能、命令别名设置、作业控制以及前后台任务管理。此外,还涵盖了编程脚本编写和通配符的使用方法,为初学者提供了全面的指导。 ... [详细]
  • zabbix 自定义监控
    配置自定义监控,我们需要配置监控项的key,和监控项返回的value添加自定义监控key的格式,在配置文件中添加UserParameter ... [详细]
  • 安装配置_安装配置MongoDB数据库
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了安装配置MongoDB数据库相关的知识,希望对你有一定的参考价值。   &n ... [详细]
  • Shell脚本统计文件行数转自http:www.jb51.netarticle61943.htm示例:row_count.sh文件awk{printNR}row_co ... [详细]
author-avatar
轻点指尖划过秋天的一抹痕8023意
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有