目的呢就是单纯的与大家分享,下面是Shell的一段

作者: 操作系统  发布:2019-11-06

    作为一个天天与Linux打交道,并以此为生的Linux运维工程师,最常用的工具性语言恐怕就是shell了, 而对于大多数的Linux和一些类Unix而言,其默认的shell就是Bash。使用Bash一般有两种场景,一是直接使用命令,二是,将这些命令组合起来,加上逻辑判断、循环、加上异常文本处理工具、加上函数构成shell脚本。用于自动、快速的执行某些批量操作。

Shell 简介

Shell作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

常常作为批处理命令来使用,用来提高生产效率!

图片 1

    为达到某个目的,Bash往往有多种实现方法,比如在脚本中   反引号 ` `   与$() 是相同的, 这种特性提供方便的同时也为代码的复杂度和可读性带来一定的影响,Bash没有所谓的规范,只有所谓不同的使用习惯,如下是我平时使用时的一些积累,同时也参考了许多优秀的博客,记录如下,目的呢就是单纯的与大家分享,毕竟互联网环境下就是互相分享,彼此借鉴,在原有的基础的创新,最重要的不是人云亦云,而是真正领悟之后的相互点评、思想碰撞。

入门

下面是Shell的一段简单入门程序,我们在Linux上面使用vi test.sh然后将下面的代码打进去,运行sh test.sh 即可

#!/bin/bash    

echo "Hello World !"

上面这段程序是输出HelloWorld,其中#!/bin/bash 指定编译器,必须在脚本的第一行,echo输出信息,这里为输出Hello World

如何运行这段程序呢, 第一步首先进入到该脚本所在的目录,比如cd /root/shelltest ,运行命令sh test.sh 这样就可以进行输入了。

使 Bash 工作的更好的技巧。

   1.添加注释

程序中的变量

每个行业都有一个该行业的大师们最常使用的工具。 对于许多系统管理员来说,这个工具就是他们的 shell。 在大多数 Linux 和其他类 Unix 系统上,默认的 shell 是 Bash。

        这个不用过多解释,无论哪种语言这甚至都是必须的,目的是增强可读性,节约他人和以后的自己熟悉脚本的时间。

定义全局变量

全局变量一直存在,不会因为切换shell终端或者退出登录而消失,全局变量需要在 /root/.bush_profile 、/etc/bashrc、/etc/profile、/etc/profile.d文件中设置,设置的格式为export name=value

在/etc/profile中定义完成后,需要重新加载配置文件 source /etc/profile

图片 2

其中在/etc/profile.d设置shell脚本可以在启动shelle客户端的时候就执行这个脚本,这个文件夹中存储的都为脚本。

创建脚本内容如下

图片 3

则新打开客户端的时候则会执行这个脚本,输出对应的内容。

图片 4

Bash 是一个相当古老的程序——它起源于 20 世纪 80 年代后期——但它建立在更多更老的 shell 上,比如 C shell(csh),csh 至少是它 10 年前的前辈了。 因为 shell 的概念是那么古老,所以有大量的神秘知识等待着系统管理员去吸收领悟,使其生活更轻松。

   2.构建一种一致的格式

定义局部变量, 局部变量在退出Shell客户端时会失效

图片 5

我们来看看一些基础知识。

       我这里主要指的是缩进 1-- 使用空格(2个或者4个,我一般用4个)取代tab。  2--代码分层要明确,属于一级的要对其,这一点Python做的很好,强制要求的。这样写出来的shell自己看着心情也不同。

单引号双引号的区别

单引号:原样输出

双引号:如果里面有变量,会输出变量

没有引号:输出变量

图片 6

在某些时候,谁曾经无意中以 root 身份运行命令并导致某种问题? 举手

    3.编码习惯上的一些注意

传递的参数

可以在调用脚本的时候给脚本传递参数,脚本内使用$1 $2 ...... 接受传递的参数,当参数超过9的时候,需要用花括号括起来 ${10}

特殊的调用参数:

    $0:返回Shell文件名称
    $$:当前脚本的PID
    $#:传递的所有参数
    $@:程序中的所有参数,这是将参数传递给其他程序的最佳方式。
    $! :执行的上一个命令的PID
    $?:上一次指令的返回值
    $_:此命令前面的最后一个参数
    $* :获取所有的参数

图片 7

图片 8

我很确定我们很多人一度都是那个人。 这很痛苦。 这里有一些非常简单的技巧可以防止你再次碰上这类问题。

       这里纯属个人习惯,但如下这样做的好处是使代码风格更统一,目的还是提高可读性

不同脚本之间访问变量

使用sh命令启动的脚本,则在脚本结束其内部的属性都会消失,其他的脚本不能访问其内部的属性。

图片 9

使用source 命令启动脚本,则在脚本结束后其属性不会失效,同时其他的脚本也能访问到。

图片 10

 

       1--使用花括号 { } 。 用花括号括起来所有的变量名。比如  ${name}  而不是 $name   

取消变量

使用unset可以取消变量,这个变量包括环境变量和局部变量

图片 11

使用别名

首先,为 mvrm 等命令设置别名,指向 mv -irm -i。 这将确保在运行 rm -f /boot 时至少需要你确认。 在 Red Hat 企业版 Linux 中,如果你使用 root 帐户,则默认设置这些别名。

如果你还要为普通用户帐户设置这些别名,只需将这两行放入家目录下名为 .bashrc 的文件中(这些也适用于 sudo ):

  1. aliasmv='mv -i'
  2. aliasrm='rm -i'

 

       2--计算表达式中用$() 代替反引号 ``   这样易于阅读。

数组

数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似),数组下标从0开始。

定义数组

    array=(value1 value2 value3)

    array_name[0]=value0

读取数组

${array_name[index]}

获取数组中全部的元素

${my_array[@]}

获取数组的长度

${#my_array[*]}

让你的 root 提示符脱颖而出

你可以采取的防止意外发生的另一项措施是确保你很清楚在使用 root 帐户。 在日常工作中,我通常会让 root 提示符从日常使用的提示符中脱颖而出。

如果将以下内容放入 root 的家目录中的 .bashrc 文件中,你将看到一个黑色背景上的红色的 root 提示符,清楚地表明你(或其他任何人)应该谨慎行事。

  1. export PS1="[$(tput bold)$(tput setab 0)$(tput setaf 1)]u@h:w # [$(tput sgr0)]"

实际上,你应该尽可能避免以 root 用户身份登录,而是通过 sudo 运行大多数系统管理命令,但这是另一回事。

使用了一些小技巧用于防止使用 root 帐户时的“不小心的副作用”之后,让我们看看 Bash 可以帮助你在日常工作中做的一些好事。

 

     

流程控制

控制你的历史

你可能知道在 Bash 中你按向上的箭头时能看见和重新使用你之前所有(好吧,大多数)的命令。这是因为这些命令已经保存到了你家目录下的名为 .bash_history 的文件中。这个历史文件附带了一组有用的设置和命令。

首先,你可以通过键入 history 来查看整个最近的命令历史记录,或者你可以通过键入 history 30 将其限制为最近 30 个命令。不过这技巧太平淡无奇了(LCTT 译注: vanilla 原为香草,后引申没拓展的、标准、普通的,比如 vanilla C++ compiler 意为标准 C++ 编译器)。 你可以更好地控制 Bash 保存的内容以及保存方式。

例如,如果将以下内容添加到 .bashrc,那么任何以空格开头的命令都不会保存到历史记录列表中:

  1. HISTCONTROL=ignorespace

如果你需要以明文形式将密码传递给一个命令,这就非常有用。 (是的,这太可怕了,但它仍然会发生。)

如果你不希望经常执行的命令充斥在历史记录中,请使用:

  1. HISTCONTROL=ignorespace:erasedups

这样,每次使用一个命令时,都会从历史记录文件中删除之前出现的所有相同命令,并且只将最后一次调用保存到历史记录列表中。

我特别喜欢的历史记录设置是 HISTTIMEFORMAT 设置。 这将在历史记录文件中在所有的条目前面添加上时间戳。 例如,我使用:

  1. HISTTIMEFORMAT="%F %T  "

当我输入 history 5 时,我得到了很好的完整信息,如下所示:

  1. 1009  2018-06-1122:34:38  cat/etc/hosts
  2. 1010  2018-06-1122:34:40  echo $foo
  3. 1011  2018-06-1122:34:42  echo $bar
  4. 1012  2018-06-1122:34:44  ssh myhost
  5. 1013  2018-06-1122:34:55  vim.bashrc

这使我更容易浏览我的命令历史记录并找到我两天前用来建立到我家实验室的 SSH 连接(我一次又一次地忘记......)。

 

    4.比较变量的值时建议采用双引号将变量括起来。如下:

if

如果else语句中没有执行语句,不可以写

if condition
then
    command1 
    command2
    ...
    commandN 
fi

------------------

if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi

------------
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

Bash 最佳实践

我将在编写 Bash 脚本时最好的(或者至少是好的,我不要求无所不知)11 项实践列出来。

11、 Bash 脚本可能变得复杂,不过注释也很方便。 如果你在考虑是否要添加注释,那就添加一个注释。 如果你在周末之后回来并且不得不花时间搞清楚你上周五想要做什么,那你是忘了添加注释。

10、 用花括号括起所有变量名,比如 ${myvariable}。 养成这个习惯可以使用 ${variable}_suffix 这种用法了,还能提高整个脚本的一致性。

9、 计算表达式时不要使用反引号;请改用 $() 语法。 所以使用:

  1. for  filein $(ls);do

而不使用:

  1. for  filein`ls`;do

前一个方式是可嵌套的,更易于阅读的,还能让一般的系统管理员群体感到满意。 不要使用反引号。

8、 一致性是好的。 选择一种风格并在整个脚本中坚持下去。 显然,我喜欢人们选择 $() 语法而不是反引号,并将其变量包在花括号中。 我更喜欢人们使用两个或四个空格而不是制表符来缩进,但即使你选择了错误的方式,也要一贯地错下去。

7、 为 Bash 脚本使用适当的释伴shebang(LCTT 译注:Shebang,也称为 Hashbang ,是一个由井号和叹号构成的字符序列 #! ,其出现在文本文件的第一行的前两个字符。 在文件中存在释伴的情况下,类 Unix 操作系统的程序载入器会分析释伴后的内容,将这些内容作为解释器指令,并调用该指令,并将载有释伴的文件路径作为该解释器的参数)。 因为我正在编写Bash脚本,只打算用 Bash 执行它们,所以我经常使用 #!/usr/bin/bash 作为我的释伴。 不要使用 #!/bin/sh#!/usr/bin/sh。 你的脚本会被执行,但它会以兼容模式运行——可能会产生许多意外的副作用。 (当然,除非你想要兼容模式。)

6、 比较字符串时,在 if 语句中给变量加上引号是个好主意,因为如果你的变量是空的,Bash 会为这样的行抛出一个错误:

  1. if[ ${myvar}=="foo"];then
  2. echo"bar"
  3. fi

对于这样的行,将判定为 false

  1. if["${myvar}"=="foo"];then
  2. echo"bar"
  3. fi

此外,如果你不确定变量的内容(例如,在解析用户输入时),请给变量加引号以防止解释某些特殊字符,并确保该变量被视为单个单词,即使它包含空格。

5、 我想这是一个品味问题,但我更喜欢使用双等号( == ),即使是比较 Bash 中的字符串。 这是一致性的问题,尽管对于字符串比较,只有一个等号会起作用,我的思维立即变为“单个 = 是一个赋值运算符!”

4、 使用适当的退出代码。 确保如果你的脚本无法执行某些操作,则会向用户显示已写好的失败消息(最好提供解决问题的方法)并发送非零退出代码:

  1. # we have failed
  2. echo"Process has failed to complete, you need to manually restart the whatchamacallit"
  3. exit1

这样可以更容易地以编程方式从另一个脚本调用你的脚本并验证其成功完成。

3、 使用 Bash 的内置机制为变量提供合理的默认值,或者如果未定义你希望定义的变量,则抛出错误:

  1. #this sets the value of $myvar to RedHat,and prints 'redhat'
  2. echo ${myvar:=redhat}
  1. #this throws an error reading 'The variable myvar is undefined, dear reader'if $myvar isundefined
  2. ${myvar:?The variable myvar isundefined, dear reader}

2、 特别是如果你正在编写大型脚本,或者是如果你与其他人一起开发该大型脚本,请考虑在函数内部定义变量时使用 local 关键字。 local 关键字将创建一个局部变量,该变量只在该函数中可见。 这限制了变量冲突的可能性。

1、 每个系统管理员有时必须这样做:在控制台上调试一些东西,可能是数据中心的真实服务器,也可能是虚拟化平台的虚拟服务器。 如果你必须以这种方式调试脚本,你会感谢你自己记住了这个:不要让你的脚本中的行太长!

在许多系统上,控制台的默认宽度仍为 80 个字符。 如果你需要在控制台上调试脚本并且该脚本有很长的行,那么你将成为一个悲伤的熊猫。 此外,具有较短行的脚本—— 默认值仍为 80 个字符——在普通编辑器中也更容易阅读和理解!

我真的很喜欢 Bash。 我可以花几个小时写这篇文章或与其他爱好者交流优秀的技巧。 就希望你们能在评论中留下赞美。


via:

作者:Maxim Burgerhout 选题:lujun9972 译者:Flowsnow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Linux公社的RSS地址:

本文永久更新链接地址

图片 12

       这样写的好处至少有: 当变量为空时依然可以执行。   当变量中有特殊字符时(接收用户输入的情况下)依然可以执行。

for

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
#!/bin/bash

if [ ${name} == "wencheng" ];then
    echo "hello"
fi

#####推荐使用如下
#!/bin/bash

if [ "${name}" == "wencheng" ];then
    echo "hello"
fi

#

while

while condition
do
    command
done

    5.异常退出时要使用异常退出代码   如:    exit 500   。这样在此脚本被其他调用时能够更好的判断是否执行完成,如若错误也能判断错误类型。

until

类似do-while循环,在最后判断条件,最少执行一次

until condition
do
    command
done

    6.尽量避免单行代码过长的问题。 这样在不同的终端,都能够正常的显示。

case

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

    7.避免命令的复杂性,这个是仁者见仁智者见智的问题,有的时候你是发现不了自己代码的臃肿程度的。比如:

函数

demoFun(){   // 定义  
    echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun   // 调用,如果需要传递参数直接在后面跟就好  demoFun 1 2 3
echo "-----函数执行完毕-----"

      grep  cut  等组合使用达到的效果就不如 awk 来的直接。

运算符

  • expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

  • expr 2 + 2 使用方法 , 需要注意的为1.表达式和运算符之间要有空格 2. 需要用``引起来

      借用一个例子:

关系运算符

图片 13

使用方法:

if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi

      检索用户ID为502的用户:  (第三种会比较的高效)

布尔运算符

图片 14

使用方法

if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
#一。
   cat  /etc/passwd | grep 502 |cut -d: -f1

#二。
   grep 502 /etc/passwd |awk -F":" '{print $1}'

#三。
   awk -F ":" '$3 == 502{print $1}' /etc/passwd

逻辑运算符

图片 15

   

字符串运算符

图片 16

   先总结这些,欢迎指正。

文件测试运算符

图片 17

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-11/148322.htm

图片 18

    另外附上控制输出终端颜色的方法 :       

        

    

本文由9159.com发布于操作系统,转载请注明出处:目的呢就是单纯的与大家分享,下面是Shell的一段

关键词: