`
姜太公
  • 浏览: 74890 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

Bash系列:从命令行开始

阅读更多
Shell的精髓在于命令行
       ---无名氏语
 
先从几个简单的命令开始,认识Shell中命令
echo hello 
echo -n hello
rm -f hello; touch hello
curl http://www.google.com/ | less
 
选项和参数
先看第一个,这个最简单了,它只是简单打印一个hello字符串。其中echo是命令部分,hello是参数部分。
第二个命令之比第一个多了一个-n,一般我们把-n叫做选项,这个选项告诉echo命令输出完hello之后不要擅作主张再输出个换行符。
到这里有必要说明下选项和参数,两者有什么联系和区别呢。
从以前的经验中我们也能感觉到,选项对命令的功能起到一定的定制作用,在命令基本功能的基础上加一点定制化的东西。比如上面的echo命令,它的基本功能就是把参数打印出来,-n这个选项定制了:不要输出默认情况下会输出的换行符。ls的基本功能是列出当前目录下的内容,-l选项定制:输出比较详细的信息。如果我自己写了一个程序myecho,它的功能是逐行输出给定的参数。C 代码如下:

#include<stdio.h>

int main(int argc,char *argv[])
{
 int i=0;
 for(i=0; i<argc; i++)
 {
  printf("%s\n", argv[i]);
 }
 return 0;
}

gcc -o myecho myecho.c

./myecho -n hello world

输出:

./myecho                                                                                                                        
-n                                                                                                                              
hello                                                                                                                           
world
这里输出的,就是程序接收到的参数列表。可见,长的很像“选项”的-n在这里也和hello一样,都是普通参数。在代码层面上,只有参数,没有选项,所谓选项,只不多是程序为了增强自己的适应性,主动设定了一些特殊参数,当这些特殊参数存在时,就执行相应的定制功能。
在Shell里,常见的有三种风格的选项:
1   UNIX风格, 用中划线开始的可分组形式,比如grep -oP,也可以写作grep -o -P
2   BSD风格,不带中划线的可分组形式,比如ps aux,也可以写作ps a u x
3   GNU风格,两个中划线加长单词,比如grep --ignore-case,等效于grep -i,优点是可读性较好,缺点是写起来比较麻烦
每种命令都有自己支持的选项,命令不同,选项的风格也不同,有些命令支持多种风格的选项,比如ps支持上面全部三种,grep支持unix和gnu风格的选项。使用命令前最好--help一下,看看命令支持哪些选项。
 
一些概念
    先约定两个名词:语句表示在Shell输入的整个一行内容,命令则是指一个可行的指令。比如在命令行中输入less -f log|grep sql然后回车,那么less -f log|grep sql是一个语句,less和grep则是其中的命令。
 
简单命令
 
先看这条语句:
echo -n hello > abc &
echo是命令(它可能是磁盘的程序,也可能是shell内建的命令),-n和hello是参数,>是重定向描述符,&表示后台执行。
这条语句虽然包含的成分比较多,但它只有一个命令(可执行部分)。像这种只有一个可执行部分的语句叫做简单命令(Simple command),是Shell里的执行单元
 
退出状态
退出状态是shell中一个很重要概念。 每个命令结束时都会返回给操作系统一个 退出状态码 (有时候也被称为 返回状态 ). 一般约定成功的命令返回0, 而不成功的命令返回非零值, 非零值通常都被解释成一个错误码. 行为良好的UNIX命令, 程序, 和工具都会返回0作为退出码来表示成功, 虽然偶尔也会有例外。之所以退出状态很重要,因为Shell是根据退出状态作为判断命令是否成功执行的依据,很多场合里,退出状态起到布尔值的作用,比如 if,while,for都用命令的退出状态。特殊变量?(没错,就是一个问号)里保存了上一个命令的退出状态,在命令行里,可以执行echo $?查看变量?的值。
 
前面说到简单命令,它的退出状态是这样的:如果命令执行完毕,自己退出,它的退出状态就是它返回给操作系统的退出状态。如果它是执行过程中被信号KILL掉,它的退出状态就是128+信号值。
例子:
jjz@JJZ:~$ echo hello
hello
jjz@JJZ:~$ echo $?
0                                        #这里的0就是echo的退出状态。
jjz@JJZ:~$
 
再来个有信号的例子:

 

jjz@JJZ:~$ sort
^C                                      #这里按下ctrl+C
jjz@JJZ:~$ echo $?
130                                    #ctrl+C是信号SIGINT,它的值是2,所以退出状态时128+2=130。可以用man 7 singal查看所有标准信号的值。                                                        

 
 
管道
管道可谓是Shell中最激动人心的特性,正因为有了管道,Shell才能把众多的Linux工具整合起来,完成强大的功能。
curl http://www.google.com/ | less 就是用了管道。显然,这不是一个简单命令,因为它有两个可执行部分:curl和less。简单的来说,管道的作用是把前一个命令的标准输出重定向到后一个命令的标准输入,也就是前一个命令的输入当成了后一个命令的输入。关于管道和重定向的细节,详见后文。
 
一般情况下管道的退出状态是最后一个执行的命令的退出状态。 (二般情况和bash的一个名叫pipefail的选项有关,这东西太少用,此处不再赘述)
 
命令列表
顾名思义,命令列表就是把命令写成一个列表(汗...),rm -f hello; touch hello就是命令列表,这里使用了分号作为命令分隔符。除了分号外,还可以使用||和&&。
rm -f hello || touch hello
rm -f hello && hello
 
三者的区别在于分号只是纯粹的分割,前面命令的执行效果不会对后面的命令产生影响。而||和&&具有布尔表达式的短路效果,还记得Java 里的判断吗
if (a&&b)... 这种情况下,如果a是false,那么表达式a&&b的值就是false,不会再测试b。
if (a||b)... 这种枪口下,如果a是true,那么表达死a||b的值就是true,不会再测试b。
和java里的判断类似,对于&&来说,只有第一个命令执行成功(退出状态是0),才会执行第二个命令,否则不执行第二个命令。||就刚好相反,如果第一个命令执行失败(退出状态非0),才会执行第二个命令,否则不会执行第二个命令。
 
列表的退出状态是列表中最后一个执行的命令的退出状态。对于a&&b,如果a的退出状态非0,b根本不会执行,a才是最后一个执行的命令,列表的退出状态就是a的退出状态。
 
复合命令
复合命令的形式比较多,控制结构也算复合结构。
(list): 在子Shell中执行命令列表(里面也可以是简单命令),简单的说,就是当前Shell会创建一个新的Shell进程,在新的Shell进程里执行 list里的命令。意义何在?如果修改了环境变量,可以保证当前环境变量不会对括号里的命令产生影响。
当然,也可以在括号里先设置一些环境变量,给里面的命令使用,而且不会对当前环境造成影响。
 
{list}:在当前环境执行,和普通的命令列表不同的是,这里的list构成一个“组”,可以简单的认为它们就是一个命令(当然,还是有顺序执行的)。
{ echo helo; echo world; }>abc 文件abc的内容有两行,分别是hello和world
echo helo; echo world; >abc  abc的内容是空的
 
两者的退出状态都是其中的命令列表的退出状态。
 
关于{}还有一点要注意的是花括号{}和list直接要有空格,而且最后一个命令后面必须有分号; 圆括号()这无此限制。要解释这个,就要说说Bash的元字符(Metacharacter)和保留字(Reserved  words)
 
元字符,保留字,引用
Shell中命令和参数使用空格(space)或制表符(tab)分隔的。这两中字符叫做"blank"
有些字符具有特殊的含义,用来分隔token,叫做元字符。下面都是元字符
|  & ; ( ) < > space tab
 
Shell处理命令行的第一步就是用元字符把语句分隔成多个token,比如语句 curl http://www.google.com/ | less,Shell首先用元字符把它分成如下token: curl, http://www.google.com/, |和 less。后面讲到Shell如何处理语句时会详细解释,详见后文。
 
还有些字符具有特殊含义,执行控制功能,叫做控制字符,下面都是控制字符
|| & && ; ;; ( ) | |& <newline>
 很明显,控制字符的作用就是控制。 比如|就有管道的作用, &具有使命令后台执行的功能。它们两个同时也是元字符,立场很不坚定。
 
每种语言都有保留字,在 java里,while,if等都是保留字,Shell当然也有自己的保留字,如下所示:
! case  do done elif else esac fi for function if in select then until while { } time [[ ]]
 
保留字本身没甚么特别之处,只是程序语言说:“这些单词和符号我自己用,你们不准使用”,于是它们就成了保留字。

 

引用
这个概念出镜率非常高。
如果我想输出一个左圆括号(,直接执行 echo (是不行的,不信你可以试试,(在Shell里是特殊字符,这时候就需要引用"上场"了:echo '('或者echo "("都可以。
引用难道就是字符两边加上单引号或双引号?这个答案算部分正确,引用的目的是去除元字符和保留字的特殊意义,加引号只是手段罢了。关于引用的详细描述,以及单引号和双引号的区别。详见后文。
分享到:
评论

相关推荐

    Linux 技巧: 从命令行创建像素标尺

    这是一个shell脚本,通常用于自动化执行一系列命令行操作。在这个特定的场景中,它很可能包含了创建像素标尺的指令。创建像素标尺可能涉及到生成一个图像文件,该文件以像素为单位显示标尺的刻度。通常,我们可以...

    Linux系统管理员必备:常见命令行工具与操作指南

    内容概要:本文详细介绍了一系列常见的Linux命令行工具及操作方法,涵盖了从基本的文件与目录管理如创建、删除、复制文件和目录,以及更复杂的功能如权限变更、磁盘使用情况检查和进程终止等方面的操作命令;...

    ghutil:从命令行与GitHub交互

    **ghutil:从命令行与GitHub交互** **一、引言** `ghutil` 是一个用 Python 编写的命令行工具,它允许用户方便地与 GitHub API 进行交互,从而实现对GitHub仓库的管理、文件操作、问题跟踪、拉取请求等一系列功能...

    ticker.sh:从命令行实时股票行情

    `jq` 提供了一系列强大的过滤、转换和操作JSON数据的命令,使得在命令行环境中处理JSON数据变得非常方便。 `yahoo-finance-api` 是一个用于获取Yahoo Finance数据的API库,它允许开发者通过HTTP请求获取股票报价、...

    详解Bash命令行处理

    Bash首先将输入的命令行拆分为一系列记号,这些记号是由特定的元字符分隔开的,包括空格、制表符、换行符、分号、圆括号、尖括号、竖线(|)和与符号(&)。这些记号可以是单词、关键字、I/O重定向符号或分号。 ###...

    LinuxCLAndShell:Linux命令行和Shell编程学习

    Shell编程,通常是使用Bash Shell,允许用户编写脚本自动执行一系列命令。掌握基本的Shell编程技巧,如变量、条件语句、循环结构、函数和错误处理,可以显著提高工作效率。 例如,你可以创建一个简单的Shell脚本来...

    philips-tv:通过命令行控制Philips(2016、2017、2018、2019)Android TV的工具

    在Philips-tv工具中,Bash被用来编写一系列指令,这些指令可以模拟用户在电视遥控器上进行的操作,如切换频道、调整音量、打开应用等。 Philips TV API客户端是这款工具的核心部分。API(Application Programming ...

    shell-talk:来自命令行的演示

    Shell脚本则是一种利用Shell语法编写的程序,可以自动化一系列的命令执行过程。 Shell-Talk 的功能主要围绕以下几个方面: 1. **颜色和高亮**:在演示过程中,Shell-Talk 可以对输出文本进行颜色编码和高亮,使...

    bananapants:在命令行中获取最新的Ruby Tapas

    在命令行中获取最新的Ruby Tapas,意味着我们将探讨如何通过命令行界面来订阅和访问这些教程。 在Ruby社区,命令行工具是开发者常用的交互方式,它允许高效、直接地与系统进行交互。对于获取Ruby Tapas,这可能涉及...

    Bash 脚本教程 – 适合初学者的 Linux Shell 脚本和命令行.docx

    Bash(Bourne-Again SHell)是Unix和Linux系统中最常用的命令行解释器,它允许用户通过脚本执行一系列自动化任务。Bash脚本是一种强大的工具,能够帮助你提高工作效率,简化日常的系统管理任务。下面我们将深入探讨...

    jqnpm:为命令行JSON处理器jq构建的程序包管理器

    1. **安装jqnpm**:首先确保系统中已经安装了jq,然后可以通过curl或者wget下载并安装jqnpm,通常是一条简单的bash命令。 2. **初始化项目**:在项目目录下运行jqnpm初始化命令,创建一个配置文件,用于记录项目的...

    DB2V97命令.pdf

    - **第5章:从命令行处理器调用命令帮助**:指导用户如何获取命令的帮助信息,包括基本的命令格式、参数说明等。 - **第6章:从命令行处理器调用消息帮助**:提供了如何查看与命令相关的错误消息和警告信息的方法...

    蔡氏电路matlab仿真代码-Git-basic:使用命令行记录您的git操作

    使用命令行记录您的git操作 1.什么是Git? 您的团队有一个项目,团队中的每个成员都必须从事该项目。 就像这个人在编辑一些东西,添加几行代码。 手动地,当A先生进行一些修改时,必须通知整个小组。 A先生将把新...

    bash入门学习实例

    这篇教程将通过一系列实例,帮助初学者了解并掌握Bash的基本用法。 ### 1. Bash shell介绍 Bash是GNU项目的一部分,由Brian Fox在1987年创建,并由Chet Ramey维护至今。它继承了Unix的原始shell,Bourne shell(sh...

    Bashscript:该存储库专用于bash脚本,可以对其进行编程以在Linux中执行自动化任务

    Bash脚本允许用户编写一系列命令,以实现一次性执行多个操作,或者根据特定条件进行动态响应,极大地提高了工作效率。 **1. Bash脚本基础** - **变量**:Bash脚本支持变量,用于存储数据。例如,`NAME="John"`,...

    取命令行—简单应用.e.rar

    例如,`.bashrc`或`.bash_profile`文件用于配置用户的bash shell环境。 9. **权限管理**:命令行中的`chmod`命令用于改变文件或目录的权限,这对于保证系统安全至关重要。 10. **网络操作**:命令行也提供了如`...

    bash脚本:我自己的bash脚本集合

    在这个名为"bash脚本:我自己的bash脚本集合"的压缩包中,我们可以预见到包含了一系列作者自定义的bash脚本,可能涵盖了从系统管理到数据迁移等多种功能。 bash,全称Bourne-Again SHell,是GNU项目的一部分,它是...

    快乐的linux命令行

    - **绝对路径**:表示从根目录开始的完整路径,如`/home/user/documents`。 - **相对路径**:表示相对于当前目录的路径,如`../documents`,其中`..`表示父目录。 - **有用的快捷键**:例如,`Tab`键可用于命令或...

Global site tag (gtag.js) - Google Analytics