【Linux篇】Shell脚本语法

前言

在安卓源码里,离不开两个东西,一个就是.sh文件,还有一个就是.mk文件。

这两个文件各持有一个语法,一个是Makefile语法,一个是Shell脚本语法。

这两个是真的让我头疼,就像看天书一样,呜呜呜。



1、变量

完整的变量打印:

name="乌鸡哥"
echo ${name}

简写:

name="乌鸡哥"
echo $name

乌鸡哥

实例:
变量
一开始没有namess这个变量,所以没有输出。

后来我添加了,就有输出了。

最后我删除了变量namess,又没有输出了。

扫描二维码关注公众号,回复: 15383423 查看本文章

1)变量输出长度

name="乌鸡哥"
echo ${
    
    #name}

4


2)提取子字符串

以下实例从字符串第 2 个字符开始截取 4 个字符:

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

注意:第一个字符的索引值为 0。


3)查找子字符串

查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

string="runoob is a great site"
echo `expr index "$string" io`  # 输出 4

注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。

4)单引号和双引号的区别

在 shell 脚本中,echo 命令用于输出字符串或者变量的值。在使用 echo 命令时,可以使用反引号、单引号或双引号来包围要输出的内容。

你们猜猜下面打印结果是什么?

name="乌鸡哥"
name2='${name}'
name3="${name}"
...
echo $name
echo $name2

结果如下:

乌鸡哥
${name}
乌鸡哥

  1. 反引号(``):反引号用于将要执行的命令包围起来,并将命令的输出作为参数传递给 echo 命令。例如:

    echo "Today is `date +%A`"
    

    这个命令会将 date +%A 命令输出的结果插入到 echo 命令中进行输出。

  2. 单引号('):单引号用于将其中的内容视为字面值进行输出,不进行任何解释和替换。例如:

    echo 'The value of $HOME is' $HOME
    

    这个命令会输出 The value of $HOME is /home/user,其中 $HOME 被视为普通字符输出,而不会被解释为变量。

  3. 双引号("):双引号用于将其中的内容进行变量替换和转义解析等操作,并将其作为一个整体进行输出。例如:

    name='John'
    echo "Hello, $name!"
    

    这个命令会输出 Hello, John!,其中 $name 会被自动替换为变量的值。

需要注意的是,在使用双引号和反引号时,如果其中包含特殊字符或者空格等不安全的字符,需要进行适当的转义处理,以避免出现意外的错误。

单引号变量,不识别特殊语法;
双引号变量,识别特殊符号。

5)特殊变量

查看上条命令是否执行成功。

  • $?
    • 0:成功
    • 1-255:错误码

实例:

在这里插入图片描述

另外,还有几个特殊字符用来处理参数(调用函数传参,命令行传参等…):

  • $*:以一个单字符串显示所有向脚本传递的参数。如$*用「“」括起来的情况、以”$1 $2 … $n"的形式输出所有参数。
  • $@:与$*相同,但是使用时加引号,并在引号中返回每个参数。如$@用「“」括起来的情况、以”$1" “ 2 " … " 2" … " 2""n” 的形式输出所有参数。
  • $$:脚本运行的当前进程ID号
  • $!:后台运行的最后一个进程的ID号
  • $#:传递到脚本的参数个数
  • $-:显示Shell使用的当前选项,与set命令功能相同。
  • $?:显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。还有一个作用就是函数返回值在调用该函数后通过 $? 来获得

6)脚本里变量的赋值情况

  1. 每次调用bash/sh解释器,都会开启一个子shell,不保留当前的shell变量,通过pstree检查进程树。(用bash执行脚本里面的变量赋值不被保存)
  2. source.是在当前shell环境加载脚本,因此保留变量。(用source执行脚本里面的变量赋值会被保存)
    变量的特殊情况

7)变量存储命令的内容

name=ls
#显示ls
echo $name
name='ls'
#显示当前目录的文件
echo ${name}

8)环境变量

环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境、保证shell命令的正确执行。

shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即丢失,如要永久生效,需要修改环境变量配置文件。

某个远程登录用户专属配置文件(局部变量)

  • ~/.bash_profile(系统优先加载所有全局环境变量和 shell 函数)
  • ~/.bashrc (在 ~/.bash_profile中被加载,相当于套娃),用户在登录的时候会去加载~/.bash_profile~/.bashrc文件

所有用户共有(全局变量)

  • /etc/profile (系统优先加载)
  • /etc/bashrc ,且系统建议最好创建在 /etc/profile.d/,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户

在 Linux 和类 Unix 系统中,全局的 Bash Shell 配置数据通常被保存在 /etc/profile 与 /etc/bashrc 文件中。这些文件包含所有用户共享的系统级别的配置和环境变量信息。

当操作系统启动时,Bash Shell 会首先执行 /etc/profile 脚本以加载所有全局环境变量和 shell 函数。对于每个新的 Bash 终端窗口,系统还将自动执行 /etc/bashrc 文件中的某些特定配置命令。

在更推荐的做法是创建自己的配置脚本并将其存储在 /etc/profile.d/ 目录下。这样,管理员可以随意创建单独的配置文件来自定义系统级别的平台和服务特定参数,而不必修改 /etc/profile 或 /etc/bashrc 文件。

例如,可以为每个服务或应用程序创建单独的配置文件,并将其放置在 /etc/profile.d/ 目录中,该目录中的任何 .sh 文件都会被整合到系统全局的 Bash 环境中。最后,每次启动新的 Bash 终端窗口时,系统都会自动执行这些文件中包含的命令和设置环境变量,实现系统环境的自动化配置。

检查系统环境变量的命令

  • set:输出所有变量,包括全局变量、局部变量
  • env:只显示全局变量
  • declare:输出所有的变量,如同set
  • export:显示和设置环境变量值

撒销环境变量

  • unset+变量名,删除变量或函数

设置只读变量

  • readonly:只有shell结束,只读变量才失效
直接readonly 显示当前系统只读变量
[root@chaogelinux ~]# readonly name="超哥
[root@chaogelinux ~]# name="chaochao"
-bash: name: 只读变量

2、数组

支持一维数组(不支持多维数组),并且没有限定数组的大小,数组元素的下标由 0 开始编号。

1)定义数组

在 Shell 中,用括号来表示数组,初始化时不需要定义数组大小(与 PHP 类似),数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 … 值n)

array_name=(A B "C" D)

还可以单独定义数组的各个分量

数组名[下标值]=变量值

array_name[0]=value0

2)读取数组

读取数组元素值的一般格式是:

# ${数组名[下标]}
valuen=${array_name[n]}

例如:

#使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}

#我们尝试打印一下数组元素。
array_name=(A B "C" D)

echo "第二个元素为: ${array_name[1]}"
echo "第三个元素为: ${array_name[2]}"

打印出来后你觉得加了双引号的会有区别吗?
答案是没有哦,打印出来都一样。

B
C


最后

#结合上述知识点

# 取得数组元素的个数
length=${
    
    #array_name[@]}
# 或者
length=${
    
    #array_name[*]}
# 取得数组单个元素的长度
lengthn=${
    
    #array_name[n]}

3)关联数组

declare 是一个 shell 内置命令,在 Linux 和其他类 Unix 系统中都可以使用。它用于声明变量的类型和属性,以及定义函数等。下面是一些 declare 命令的常见用法:

  1. 声明普通变量
declare variable_name=value

这个命令将创建一个名为 variable_name 的变量,并将其初始化为指定的值。

  1. 声明只读变量
declare -r variable_name=value

这个命令将创建一个只读的名为 variable_name 的变量,并将其初始化为指定的值。只读变量的值不能被修改或重新赋值。

  1. 声明整数变量
declare -i variable_name=value

这个命令将创建一个名为 variable_name 的整型变量,并将其初始化为指定的值。如果后续对该变量进行了非整型的赋值操作,系统会尝试自动转换为整型。

  1. 声明数组变量
declare -a array_name

这个命令将创建一个名为 array_name 的数组变量。在后续的操作中,可以使用数组下标来访问和赋值数组元素。

  1. 声明关联数组变量
declare -A associative_array_name

这个命令将创建一个名为 associative_array_name 的关联数组变量。在后续的操作中,可以使用任意字符串作为数组下标来访问和赋值数组元素。

  1. 声明函数
declare -f function_name

这个命令将打印名为 function_name 的函数的定义。如果不加参数,则会列出所有已经定义的函数。

除了上述用法外,declare 命令还支持一些其他的选项和参数,可以通过 help declare 命令来查看它们的详细说明。

我们这里详细介绍第五点

在 Bash shell 中,关联数组(associative array)是一种特殊的数组类型,它使用任意字符串作为下标来访问和赋值数组元素。关联数组也被称为哈希表(hash table)、字典(dictionary)或映射(map)。

要声明一个关联数组变量,可以使用 declare 命令的 -A 选项,例如:

declare -A my_array

也可以这样直接定义:

declare -A my_array=(["name"]="John" ["age"]="30")

这里,我们使用关联数组下标 "name""age" 来分别给数组元素赋值。

my_array["name"]="John"
my_array["age"]=30

在后续的操作中,可以使用任何字符串作为数组下标来访问和赋值数组元素,例如:

echo "My name is ${my_array["name"]} and I am ${my_array["age"]} years old."

打印数组的所有value:

# 两者等效
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"

数组的元素为: John 30

打印数组的所有key:

echo "数组的键为: ${
     
     !site[*]}"
echo "数组的键为: ${
     
     !site[@]}"

数组的键为: name age

打印数组的元素个数:

echo "数组元素个数为: ${
     
     #my_array[*]}"
echo "数组元素个数为: ${
     
     #my_array[@]}"

数组元素个数为: 2

需要注意的是,在关联数组中,每个元素都与一个独立的字符串键相关联。因此,在访问数组元素时,可以使用任何合法的字符串作为下标,包括空字符串、特殊字符和空格等。与普通数组不同,关联数组不需要事先指定数组的长度,也不需要在定义时初始化数组元素。


3、注释

# 别学习了 好好睡觉(单行注释)
# 多行注释(Here Document)
: <<END_COMMENT
注释内容...
注释内容...
注释内容...
END_COMMENT
# 举个栗子
# 这段代码先执行 Here Document (<<)语法结构,可以看成标准输入
# 将内容传递给 cat 命令作为标准输入
# 然后再将 cat 命令的输出结果重定向(>)到文件中
# 最终将字符串 "五级五级" 和 "66666666" 写入到 77.sh 文件中。
cat > device/$1/$2/vendorsetup.sh << EOF
echo "五级五级"
echo "66666666"
EOF

4、运算符

1)算术运算符

就是加减乘除and so on。

条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成[ $a == $b ]

a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

2)关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

  • -eq:相等
  • -ne:不相等
  • -gt:左边大于右边
  • -lt:左边小于右边
  • -ge:左边大于等于右边
  • -le:左边小于等于右边
a=10
b=20

if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
   echo "$a -ne $b: a 不等于 b"
else
   echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
   echo "$a -gt $b: a 大于 b"
else
   echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
   echo "$a -lt $b: a 小于 b"
else
   echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
   echo "$a -ge $b: a 大于或等于 b"
else
   echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
   echo "$a -le $b: a 小于或等于 b"
else
   echo "$a -le $b: a 大于 b"
fi

3)布尔运算符

  • !:非
  • -o:或
  • -a:与
a=10
b=20

if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
   echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
   echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi

4)逻辑运算符

a=10
b=20

if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

5)字符串运算符

a="abc"
b="efg"

#检测两个字符串是否相等,相等返回true
if [ $a = $b ]
then
   echo "$a = $b : a 等于 b"
else
   echo "$a = $b: a 不等于 b"
fi
#检测两个字符串是否不相等,不相等返回true
if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a != $b: a 等于 b"
fi
#检测字符串长度是否为0,为0返回true
if [ -z $a ]
then
   echo "-z $a : 字符串长度为 0"
else
   echo "-z $a : 字符串长度不为 0"
fi
#检测字符串长度是否不为0,不为0返回true
if [ -n "$a" ]
then
   echo "-n $a : 字符串长度不为 0"
else
   echo "-n $a : 字符串长度为 0"
fi
#检测字符串是否不为空,不为空返回true
if [ $a ]
then
   echo "$a : 字符串不为空"
else
   echo "$a : 字符串为空"
fi

6)文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

1

file="/var/www/runoob/test.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi

5、输入输出

1)read(输入)

read -p "input your name:" str
echo "read name: $str"  

2)echo(输出)

echo `date`

3)printf(输出)

格式说明:

printf  format-string  [arguments...]

参数说明:

  • format-string: 为格式控制字符串
  • arguments: 为参数列表

举个栗子:

printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg 
  • %-10s:指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
  • %-4.2f :指格式化为小数,其中 .2 指保留2位小数
  • %s :输出一个字符串
  • %d :整型输出
  • %c :输出一个字符
  • %f :输出实数,以小数形式输出
# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"

# 没有引号也可以输出(没换行)
printf %s abcdef

# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用(没换行)
printf %s abc def

printf "%s\n" abc def

printf "%s %s %s\n" a b c d e f g h i j

# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n"

1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j
and 0

printf的特殊用法

1


6、流程控制

1)if

正常格式:

if 条件1
then
    命令1 
    命令2
    ...
    命令N 
fi

简写一行模式:

if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

多if-elseif-else模式:

if 条件1
then
    命令1
elif 条件2 
then 
    命令2
else
    命令N
fi

if else 的 ["$a" -gt "$b"]判断条件中大于使用 -gt,小于使用 -lt。
if else 的 ((a>b)) 判断条件中大于和小于可以直接使用 > 和 <。
if else 语句经常与 test 命令结合使用。

特殊:test命令

test命令是一个用于在Bash shell中测试条件的内置命令,通常被用于控制流程的判断和分支。

test命令有多种形式,最基本的语法如下:

test+选项+expression

[选项+expression ]

这里的expression表示一个特定的测试条件,可以是文件测试、字符串比较、数字比较等不同类型的操作。

test命令有多种选项可以用于测试条件,这里列举一些比较常见的选项:

  • -n string:判断字符串是否非空。
  • -z string:判断字符串是否为空。
  • -f file:判断文件是否存在且是普通文件。
  • -e file:判断文件是否存在。
  • -d file:判断文件是否存在且是目录。
  • -r file:判断文件是否存在且可读。
  • -w file:判断文件是否存在且可写。
  • -x file:判断文件是否存在且可执行。
  • -s file:判断文件是否存在且不为空。

这些选项可以用于组合不同类型的条件表达式,并配合逻辑运算符(如&&、||)实现复杂的控制流程。例如:

filename="example.txt"

if test -f "$filename" && test -r "$filename"; then
  echo "yes"
else
  echo "no"
fi

#或者

if [ -f "$filename" ] && [ -r "$filename" ]; then
  echo "yes"
else
  echo "no"
fi

#或者

if [ -f example.txt ] && [ -r example.txt ]; then
  echo "yes"
else
  echo "no"
fi

#或者
#这里使用-a选项(即逻辑与)连接两个表达式,表示需要同时满足多个条件。
if [ -f example.txt -a -r example.txt ]; then
  echo "yes"
else
  echo "no"
fi

这个例子检查文件myfile是否存在并且可读,如果两个条件都成立,就输出"yes",否则输出"no"。

需注意的是,在test命令中接受的所有参数都必须放在方括号内,每个参数之间必须用空格隔开,并保证最后一个参数与方括号之间有一个空格或其他分隔符。

需要注意的是,在bash shell中可以使用方括号[]来代替test命令,实现同样的效果。这就是上面的例子使用[ -f file.txt ]的原因。


2)for

一般格式:

for var in item1 item2 ... itemN
do
    命令1
    命令2
    ...
    命令N
done

简写一行模式:

for var in item1 item2 ... itemN; do 命令1; 命令2… done;
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
#!/bin/bash

for str in This is a string
do
    echo $str
done

This
is
a
string


3)while

一般格式:

while 条件
do
    # 可以在这里添加自己的命令
done
#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
    echo "是的!$FILM 是一个好网站"
done

在 Linux 终端中,按下 Ctrl+d 键可以执行以下不同的功能,具体取决于当前终端的上下文:

  1. 输入结束标志:当您想要从终端输入流中退出时,按下 Ctrl+d 可以指示输入结束。例如,在命令行中通过管道(|)将输出重定向到某个命令或文件中时,您可以按 Ctrl+d 表示完成输入并开始处理。

  2. 终止一个前台进程:如果您正在运行一个前台进程并想要强制停止它,可以使用 Ctrl+d 组合键来发送 SIGINT 信号。该信号会告诉应用程序停止当前操作和任何正在进行的数据处理,并退出进程。

  3. 登出当前用户:在大多数 Linux 系统中,按下 Ctrl+d 可以表示退出当前登录用户。这通常与 shell 或其他 CLI 应用程序一起使用。

总之,Ctrl+d 多种多样的作用,具体取决于您当前使用的终端上下文。在使用时,请注意其所附带的含义,并小心操作。

无限循环:

while :
do
    # 可以在这里添加自己的命令
donewhile true
do
    # 可以在这里添加自己的命令
donefor (( ; ; ))
do
   echo "loop will run forever unless you terminate it with Ctrl+c"
   # 可以在这里添加自己的命令
done


4)until

until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。

until 条件
do
    # 可以在这里添加自己的命令
done
a=0
# 输出0-9
until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done

5)case

值可以为变量或常数

一般格式:

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac
site="runoob"

case "$site" in
   "runoob") echo "菜鸟教程"
   ;;
   "google") echo "Google 搜索"
   ;;
   "taobao") echo "淘宝网"
   ;;
esac

6)break和continue

结束循环和跳出一层循环。同Java


7、函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

1)函数返回值

funWithReturn(){
    
    
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

函数返回值在调用该函数后通过 $? 来获得。

2)带参函数

funWithParam(){
    
    
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

注意:$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。


8、输入输出重定向

就是把文件内容搞过来,或者搞过去。

1)输出重定向

把乌鸡哥三个字放到这个77.txt文件中

$ echo "乌鸡哥" > 77.txt

2)输入重定向

wc -l < 文件名

其中,wc 是一个统计文本信息的命令,-l 参数表示只统计行数。< 符号表示将文件内容作为输入传入到命令中。

因此,执行这个命令后,它会读取文件 “users” 的内容,并统计其中的行数,然后输出结果。这个命令在 Unix 或 Linux 环境下经常用于查看文件的行数。


sort < input.txt > output.txt

input.txt读取文件,然后用sort排序,最后排完了再输出到output.txt


3)特殊重定向

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
ls /mnt 2>> log.txt

这个命令尝试列出 /mnt 目录中的内容。如果操作成功,则结果将直接打印到终端上;但是,如果操作失败,命令将记录相关错误信息,把错误信息通过追加的方式写入到 log.txt 文件中。当您想要获取输出并将其保存在文件中时,这种重定向技术特别有用。

ls /mnt > output.txt 2>&1

这个命令尝试列出 /mnt 目录中所有的内容。如果目录可以访问,则命令将把结果列表格式输出到 output.txt 文件中,不论这些结果是标准输出还是标准错误输出。如果存在任何错误或警告信息,则它们也将被重定向到该文件中,使您可以轻松快速地查看所有输出。注意,在使用此语法时,请确保您有足够的权限来访问输入和输出文件,并且不会覆盖或修改意外文件。


4)Here Document

Here Document 是一种在 Bash/Shell 脚本中用于向命令提供输入的语法。它允许您指定一个“限定词”(也称为分界符),然后在该分界符下方的多行文本将作为命令的标准输入进行处理。

在脚本中,Here Document 语法通常采用以下形式:

command <<LIMITER
input text
...
LIMITER

其中:

  • command 表示要接收 Here Document 作为输入的命令。
  • << 符号用于指定 Here Document 分界符,并将其留空以让 Shell 可以自动选择默认值。
  • LIMITER 是由用户指定的分界符,用于隔离输入文本并告诉 Shell 在何时停止读取标准输入。
  • input text 是最终传递给命令作为标准输入的多行文本。

注意,分界符必须从第一列开始,因此不能缩进 Here Document 中的文本。另外,当您需要在输入文本中使用变量或其他 Bash 命令时,可以在限定词前加上一个“-”符号,例如 <<-LIMITER,这会告诉 Shell 忽略输入文本中的缩进(就像 Bash 中的 heredoc 标记)。

例如,以下是一个使用 Here Document 语法的示例:

cat <<END
This is some example text that will be passed
as standard input to the cat command.
It can contain multiple lines.
END

这将创建一个名为 END 的分界符(END也可以换成pp啥都可以),并将三行文本作为标准输入传递给 cat 命令。最终,命令会将输入文本作为输出打印到终端上。


5)/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1

注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。


9、文件包含(引用)

和C语言差不多,也可以引用其他.sh脚本里面的函数、变量等等。

. filename   # 注意点号(.)和文件名中间有一空格source filename

创建两个 shell 脚本文件

A.sh文件

#!/bin/bash
name="乌鸡哥"

B.sh文件

#!/bin/bash
#使用 . 号来引用test1.sh 文件
. ./test1.sh

# 或者使用以下包含文件代码
# source ./test1.sh

echo "${name}"

$ chmod +x B.sh
$ ./B.sh
乌鸡哥

被包含的文件 A.sh 不需要可执行权限。

猜你喜欢

转载自blog.csdn.net/qFAFAF/article/details/130125945