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

shell 基础


shell 分类

常见的shell 主要分为以下几种 

bash ,dash,csh,tcsh,zsh等

shell 的内建命令与外部命令

外部命令(有时也称为文件系统命令)是存在于bash shell之外的程序。也就是说,它并不属于shell程序的一部分。
外部命令程序通常位于/bin、/usr/bin、/sbin或/usr/sbin目录中。

内建命令

嵌入到shell内部的命令,内建命令已经和shell编译成一体,作为shell的组成部分存在,无须借助外部程序文件来执行

查看内建与外部命令

[gbasedbt@gbase170 ~]$ type -a echo
echo 是 shell 内嵌
echo 是 /usr/bin/echo
[gbasedbt@gbase170 ~]$ type -a ps
ps 是 /usr/bin/ps
[gbasedbt@gbase170 ~]$ type -a cd
cd 是 shell 内嵌
cd 是 /usr/bin/cd
[gbasedbt@gbase170 ~]$ type -a exit
exit 是 shell 内嵌

可以发现 ,有些为内建命令,有些为外部命令,也有一部分为都有
在shell 中默认使用为 内建命令,如使用外部命令,可以加上全路径 
例如
echo a    --内建命令
/usr/bin/echo a  --外部命令

区别

每当执行外部命令时,就会创建一个子进程。这种操作称为衍生(forking)
在使用内建命令时,不需要衍生子进程。因此,内建命令的系统开销较低。


构建基础脚本

1 基本格式


通常以 .sh结尾
开头指明shell 类型
#!/bin/bash   
#!/bin/env bash

2 显示输出


echo aaa
echo "aaa"
echo "a'b'a"


3 使用变量

环境变量
用户自定义变量
var1=10 
var2=-57 
var3=testing 
var4="still more testing" 

用户自定义变量可以通过$引用
#!/bin/bash
days=10 
guest="Katie" 
echo "$guest checked in $days days ago" 

4 命令替换

shell 脚本中最有用的特性之一是可以从命令输出中提取信息并将其赋给变量。把输出赋给变量之后,就可以随意在脚本中使用了。

testing=`date`
testing=$(date)

5 重定向输入和输出

有时候,你想要保存命令的输出而不只是在屏幕上显示。bash shell 提供了几个运算符,它们可以将命令的输出重定向到其他位置(比如文件)。
重定向既可用于输入,也可用于输出,例如将文件重定向,作为命令输入。

输出重定向

date > test6

输出追加到已有文件中

date >> test6

输入重定向

wc -l < /etc/passwd

内联输入重定向

这种方法无须使用文件进行重定向,只需在命令行中指定用于输入重定向的数据即可

[gbasedbt@gbase170 ~]$ wc -l <<EOF
> a
> b
> c
> EOF
3

6 管道

rpm -qa | sort | more


7 执行数学运算 

expr 命令

尽管标准运算符在 expr 命令中工作得很好,但在脚本或命令行中使用时仍有问题出现。

使用方括号 
bash shell保留了 expr 命令,但同时也提供了另一种更简单的方法来执行数学运算。在bash中,要将数学运算结果赋给变量,可以使用$和方括号($[ operation ])

var1=$[1 + 5] 
var2=$[$var1 * 2]

bash shell 的数学运算符只支持整数运算。

8 浮点数解决方案

有几种解决方案能够克服bash只支持整数运算的限制。最常见的做法是使用内建的bash计算器bc。 

[root@gbase170 ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 

12 * 2.2
26.4

在脚本中使用bc

#!/bin/bash 
var1=20 
var2=3.14159 
var3=$(echo "scale=4; $var1 * $var1" | bc) 
var4=$(echo "scale=4; $var3 * $var2" | bc) 

#!/bin/bash 
var1=10.46 
var2=43.67 
var3=33.2 
var4=71 
var5=$(bc << EOF 
scale = 4 
a1 = ( $var1 * $var2) 
b1 = ($var3 * $var4) 
a1 + b1 
EOF 

在bash计算器中创建的变量仅在计算器中有效,不能在shell脚本中使用


9 退出脚本 


shell 中运行的每个命令都使用退出状态码来告诉shell自己已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由其传给shell。

查看退出状态码

echo $?

exit 命令

在默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。exit命令允许在脚本结束时指定一个退出状态码

exit 1

var1=10
exit $var1

流程控制

if-then语句

最基本的结构化命令是if-then语句。if-then语句的格式如下:

if command 
then 
commands 
fi 

if command; then 
commands 
fi 


bash shell 的 if 语句会运行if 之后的命令。如果该命令的退出状态码为0(命令成功运行),那么位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,则then 部分的命令不会被执行,bash shell会接着处理脚本中的下一条命令。fi 语句用来表示if-then 语句到此结束。

#!/bin/bash  
if pwd 
then 
     echo "it worked" 
fi

if-then-else 语句

if command 
then 
commands 
else 
commands 
fi 

if-then-elif 语句

if command1 
then 
command set 1 
elif command2 
then 
command set 2 
elif command3 
then 
command set 3 
elif command4 
then 
command set 4 
fi 

test 命令


if-then语句不能接受除命令退出状态码之外的条件。 

但是,在bash shell中有个好用的工具可以帮你使用if-then语句测试其他条件。 
test 命令可以在if-then语句中测试不同的条件。如果test命令中列出的条件成立,那么test 命令就会退出并返回退出状态码0。这样 if-then语句的工作方式就和其他编程语言中的if-then 语句差不多了。如果条件不成立,那么test命令就会退出并返回非0的退出状态码,这使得if-then语句不会再被执行。

if test condition 
then 
commands 
fi 

[ condition ] 

bash shell 提供了另一种条件测试方式,无须在if-then语句中写明test命令:

if [ condition ] 
then 
commands 
fi 

方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须留有空格,否则
就会报错。


test 命令和测试条件可以判断3类条件。 
数值比较 
字符串比较 
文件比较 


数值比较

n1 -eq n2  检查n1是否等于n2 
n1 -ge n2  检查n1是否大于或等于n2 
n1 -gt n2  检查n1是否大于n2 
n1 -le n2  检查n1是否小于或等于n2 
n1 -lt n2  检查n1是否小于n2 
n1 -ne n2  检查n1是否不等于n2 

字符串比较

str1 = str2  检查str1是否和str2相同 
str1 != str2 检查str1是否和str2不同 
str1 < str2  检查str1是否小于str2 
str1 > str2  检查str1是否大于str2 
-n str1      检查str1的长度是否不为0 
-z str1      检查str1的长度是否为0 

字符串顺序

大于号和小于号必须转义,否则shell会将其视为重定向符,将字符串值当作文件名
string1=soccer 
string2=zorbfootball 
if [ $string1 \> $string2 ] 
then 
     echo "$string1 is greater than $string2" 
else 
     echo "$string1 is less than $string2" 
fi

文件比较 

它允许测试 Linux 文件系统中文件和目录的状态。

-d file           检查file是否存在且为目录 
-e file           检查file是否存在 
-f file           检查file是否存在且为文件
-r file           检查file是否存在且可读
-s file           检查file是否存在且非空
-w file           检查file是否存在且可写
-x file           检查file是否存在且可执行
-O file           检查file是否存在且属当前用户所有
-G file           检查file是否存在且默认组与当前用户相同
file1 -nt file2   检查file1是否比file2新
file1 -ot file2   检查file1是否比file2旧


复合条件测试 

[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ] 

第一种布尔运算使用布尔运算符AND来组合两个条件。要执行then部分的命令,两个条件都必须满足。 

第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为真,那么then部分的命令就会执行。
 


 
if-then 的高级特性

bash shell 还提供了 3个可在if-then 语句中使用的高级特性。 

在子shell中执行命令的单括号。 
用于数学表达式的双括号。 
用于高级字符串处理功能的双方括号。
 
使用单括号

单括号允许在if语句中使用子shell。单括号形式的test 命令格式如下: 
(command) 
在bash shell 执行 command 之前,会先创建一个子shell,然后在其中执行命令。如果命令成功结束,则退出状态码会被设为0,then部分的命令就会被执行。如果命令的退出状态码不为0,则不执行then部分的命令。

if (echo $BASH_SUBSHELL) 
then 
     echo "The subshell command operated successfully." 
 
else 
     echo "The subshell command was NOT successful." 

fi 
 

使用双括号 

双括号命令允许在比较过程中使用高级数学表达式。test命令在进行比较的时候只能使用简单的算术操作。双括号命令提供了更多的数学符号

(( expression ))
expression可以是任意的数学赋值或比较表达式

val++     后增 
val--       后减 
++val     先增 --val 先减 
!             逻辑求反 
~            位求反 
**           幂运算 
<<          左位移 
>>          右位移 
&            位布尔AND 
|             位布尔OR 
&&         逻辑AND 
||            逻辑OR 


双括号中表达式的大于号不用转义


使用双方括号


双方括号命令提供了针对字符串比较的高级特性。

[[ expression ]]

expression 可以使用test 命令中的标准字符串比较。除此之外,它还提供了test命令所不具备的另一个特性——模式匹配。

双方括号在bash shell中运行良好。不过要小心,不是所有的shell都支持双方括号。

if [[ $BASH_VERSION == 5.* ]] 
then 
     echo "You are using the Bash Shell version 5 series." 
fi 

当在双中括号内使用==运算符或!=运算符时,运算符的右侧被视为通配符。如果使用的是=~运算符,则运算符的右侧被视为POSIX扩展正则表达式。


case 命令

有了case 命令,就无须再写大量的elif 语句来检查同一个变量的值了。case 命令会采用列表格式来检查变量的多个值

case variable in 
pattern1 | pattern2) commands1;; 
pattern3) commands2;; 
*) default commands;; 
esac 


for 命令

基础语法

for var in list 
do 
commands 
done 

读取列表中的值 

for test in Alabama Alaska Arizona Arkansas California Colorado 
do 
   echo The next state is $test 
done 

读取列表中的复杂值

for test in I don\'t know if "this'll" work 
do 
   echo "word:$test" 
done 

for test in Nevada "New Hampshire" "New Mexico" "New York" 
do 
   echo "Now going to $test" 
done 

从变量中读取值列表

list="Alabama Alaska Arizona Arkansas Colorado" 
for state in $list 
do 
   echo "Have you ever visited $state?" 
done 

从命令中读取值列表 

file="states.txt" 
for state in $(cat $file) 
do 
   echo "Visit beautiful $state" 
done 

更改字段分隔符

IFS 环境变量
IFS 定义了bash shell用作字段分隔符的一系列字符。在默认情况下,bash shell会将下列字
符视为字段分隔符。 
空格 
制表符 
换行符 


如果bash shell在数据中看到了这些字符中的任意一个,那么它就会认为这是列表中的一个
新字段的开始。在处理可能含有空格的数据(比如文件名)时会出现问题

解决这个问题的办法是在shell脚本中临时更改IFS环境变量的值来限制被bash shell视为字
段分隔符的字符。如果想修改IFS的值,使其只能识别换行符,可以这么做:
IFS=$'\n'
将该语句加入脚本,告诉bash shell忽略数据中的空格和制表符。

IFS.OLD=$IFS 
IFS=$'\n' 
<在代码中使用新的IFS值> 
IFS=$IFS.OLD 

使用通配符读取目录

for file in /home/rich/test/* 
do 
if [ -d "$file" ] 
   then 
      echo "$file is a directory" 
   elif [ -f "$file" ] 
   then 
      echo "$file is a file" 
   fi 
done 

也可以在for命令中列出多个目录通配符

for file in /home/rich/.b* /home/rich/badtest 
do 
   if [ -d "$file" ] 
   then 
      echo "$file is a directory" 
   elif [ -f "$file" ] 
   then 
      echo "$file is a file" 
   else 
     echo "$file doesn't exist" 
   fi 
done 

C语言风格的for命令

for (( i=1; i <= 10; i++ )) 
do 
   echo "The next number is $i" 
done 


使用多个变量

尽管可以使用多个变量,但只能在for循环中定义一种迭代条件

for (( a=1, b=10; a <= 10; a++, b-- )) 
do 
 echo "$a - $b" 
done 

while 命令

while 命令在某种程度上糅合了if-then语句和for循环。while命令允许定义一个要测试的命令,只要该命令返回的退出状态码为0,就循环执行一组命令。它会在每次迭代开始时测试test命令,如果test命令返回非0退出状态码,while命令就会停止执行循环。

while test command 
do 
 other commands 
done 

until 命令 

与while 命令工作的方式完全相反,until 命令要求指定一个返回非0退出状态码的测试命令。只要测试命令的退出状态码不为0,bash shell就会执行循环中列出的命令。一旦测试命令返回了退出状态码0,循环就结束了。

until test commands 
do 
other commands 
done 

循环控制

break命令 
continue命令

break命令 

break命令是退出循环的一种简单方法。你可以用break命令退出任意类型的循环,包括while循环和until循环。

1. 跳出单个循环
#!/bin/bash 
# breaking out of a for loop 
 
for var1 in 1 2 3 4 5 6 7 8 9 10 
do 
   if [ $var1 -eq 5 ] 
   then 
      break 
   fi 
   echo "Iteration number: $var1" 
done 

2. 跳出内层循环

for (( a = 1; a < 4; a++ )) 
do 
   echo "Outer loop: $a" 
   for (( b = 1; b < 100; b++ )) 
   do 
      if [ $b -eq 5 ] 
      then 
         break 
      fi 
      echo "   Inner loop: $b" 
   done 
done 


3. 跳出外层循环

有时你位于内层循环,但需要结束外层循环。break命令接受单个命令行参数: 
break n 

for (( a = 1; a < 4; a++ )) 
do 
   echo "Outer loop: $a" 
   for (( b = 1; b < 100; b++ )) 
   do 
      if [ $b -gt 4 ] 
      then 
         break 2 
      fi 
      echo "   Inner loop: $b" 
   done 
done 

continue 命令

continue 命令可以提前中止某次循环,但不会结束整个循环。

for (( var1 = 1; var1 < 15; var1++ )) 
do 
   if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] 
   then 
      continue 
   fi 
   echo "Iteration number: $var1" 
done 

和break 命令一样,continue命令也允许通过命令行参数指定要继续执行哪一级循环: 
continue n

for (( a = 1; a <= 5; a++ )) 
do 
   echo "Iteration $a:" 
   for (( b = 1; b < 3; b++ )) 
   do 
      if [ $a -gt 2 ] && [ $a -lt 4 ] 
      then 
         continue 2 
      fi 
      var3=$[ $a * $b ] 
      echo "   The result of $a * $b is $var3" 
   done 
done

处理循环的输出

for file in /home/rich/* 
 do 
   if [ -d "$file" ] 
   then 
      echo "$file is a directory" 
   elif 
      echo "$file is a file" 
   fi 
done > output.txt

这种方法同样适用于将循环的结果传输到另一个命令

for state in "North Dakota" Connecticut Illinois Alabama Tennessee 
do 
   echo "$state is the next place to go" 
done | sort


 


 


http://www.kler.cn/news/366815.html

相关文章:

  • Java基础(7)图书管理系统
  • day3:管道,解压缩,vim
  • Redis 发布订阅 总结
  • Linux中DNS搭建
  • arthas使用 笔记
  • uniapp一键打包
  • C#实现将汉字转换成拼音
  • [Gdiplus/Gdi]_[中级]_[实现多行文本的多种颜色绘制-富文本绘制]
  • 如何通过sip信令以及抓包文件分析媒体发到哪个地方
  • DEVOPS: 容器与虚拟化与云原生
  • java第三天(游戏开发)
  • grafana 和 prometheus
  • [论文阅读] Improved Baselines with Visual Instruction Tuning
  • ubuntu(27):ubuntu20.04鼠标无法显示但远程控制可以使用
  • 51c大模型~合集4
  • 重学SpringBoot3-集成Hazelcast
  • 基于GPT的智能客服落地实践
  • 深入解析Apache DolphinScheduler容错机制
  • 如何用 obdiag 排查 OceanBase数据库的卡合并问题——《OceanBase诊断系列》14
  • Sourcetree和GitLab的结合使用
  • Mac 使用脚本批量导入 Apple 歌曲
  • 【力扣 + 牛客 | SQL题 | 每日4题】牛客大厂面试真题W3,W10
  • Protues中51单片机按键无法复位(已解决)
  • 【多态案例】电脑组装
  • 如何使用python seaborn进行复杂的数据可视化操作?
  • 使用API有效率地管理Dynadot域名,通过域名命令删除域名服务器(NS)