注册 | 登录 | QQ登陆 |

终极 Bash 脚本指南

时间:2024-08-14人气:-


内部变量

Bash 的内部变量也不少,有时我们可能会用到,如 $BASHPID $IFS $PWD 等,更多看这里 。

将命令输出分配给变量

可以使用 $(command) 将命令输出存储在变量中。例如这是一个info.sh脚本内容:

#!/bin/bash

LIST=$(ls -l)
echo "File information: $LIST"

执行(别忘了给执行权限)

$ ./info.sh
File information: total 8
-rwxrwxr-x 1 razeen razeen 85 2月   5 07:35 hello.sh
-rwxrwxr-x 1 razeen razeen 58 2月   5 07:36 info.sh

下面的脚本会将时间和日期,用户名以及系统正常运行时间保存到日志文件中。

其中 > 是重定向之一,它将覆盖文件。使用 >> 可以将输出追加到文件。

#!/bin/bash
DATE=$(date -u) # UTC 时间#!/bin/bash
DATE=$(date -u) # UTC 时间
WHO=$(whoami) # 用户名
UPTIME=$(uptime) # 系统运行时间
echo "Today is $DATE. You are $WHO. Uptime info: $UPTIME" > logfile
WHO=$(whoami) # 用户名
UPTIME=$(uptime) # 系统运行时间
echo "Today is $DATE. You are $WHO. Uptime info: $UPTIME" > logfile

image-20210205074148588

内建命令

Shell 内建命令是可以直接在Shell中运行的命令。可以这么查看内建命令:

$ compgen -b | sort
-
.
:
[
alias
autoload
bg
bindkey
break
builtin
bye
cd

也可以用 type 查看命令的类型。

$ type cd
cd is a shell builtin

可以用 which 命令查看可执行文件的文件路径:

# which sort
/usr/bin/sort

可通过 man builtins 查看内建命令的详细描述。

测试IF条件表达式

if 后面需要接者then:

if [ condition-for-test ]
then
  command
  ...
fi

或者,

if [ condition-for-test ]; then
  command
  ...
fi

如:

#!/bin/bash
 
VAR=myvar
if [ $VAR = myvar ]; then
    echo "1: \$VAR is $VAR"   # 1: $VAR is myvar
fi
if [ "$VAR" = myvar ]; then
    echo "2: \$VAR is $VAR"   # 2: $VAR is myvar
fi
if [ $VAR = "myvar" ]; then
    echo "3: \$VAR is $VAR"   # 3: $VAR is myvar
fi
if [ "$VAR" = "myvar" ]; then
    echo "4: \$VAR is $VAR"   # 4: $VAR is myvar
fi

上面,我们在比较时,可以用双引号把变量引用起来。

但要注意单引号的使用。

#!/bin/bash
VAR=myvar
if [ '$VAR' = 'myvar' ]; then
    echo '5a: $VAR is $VAR'
else
    echo "5b: Not equal."
fibas
# Output:
# 5b: Not equal.

上面这个就把 ‘$VAR’ 当一个字符串了。

但如果变量是多个单词,我们就必须用到双引号了,如

#!/bin/bash

# 这样写就有问题
VAR1="my var"
if [ $VAR1 = "my var" ]; then
    echo "\$VAR1 is $VAR1"
fi
# Output
# error [: too many arguments

# 用双引号
if [ "$VAR1" = "my var" ]; then
    echo "\$VAR1 is $VAR1"
fi

总的来说,双引号可以一直加上。

空格问题

比较表达式中,如果=前后没有空格,那么整个表法式会被认为是一个单词,其判断结果为True.

#!/bin/bash
 
VAR2=2
#  由于被识别成一个单词, [] 里面为 true
if [ "$VAR2"=1 ]; then
    echo "$VAR2 is 1."
else
    echo "$VAR2 is not 1."
fi
# Output
# 2 is 1.


# 前后加上空格就好了
if [ "$VAR2" = 1 ]; then
    echo "$VAR2 is 1."
else
    echo "$VAR2 is not 1."
fi
# Output
# 2 is not 1.

另外需要注意的是, 在判断中,中括号 [ 和变量之间一定要有一个空格,= 或者 ==。 如果缺少了空格,你可能会到这类似这样的错误:unary operator expected’ or missing ]` 。

# 正确, 符号前后有空格
if [ $VAR2 = 1 ]; then
    echo "\$VAR2 is 1."
else
    echo "It's not 1."
fi
# Output
# 2 is 1.


# 错误, 符号前后无空格
if [$VAR2=1]; then
    echo "$VAR2 is 1."
else
    echo "It's not 1."
fi
# Output
# line 3: =1: command not found
# line 5: [=1]: command not found
# It's not 1.

文件测试表达式

对文件进行相关测试,判断的表达式如下:

表达式True

file1 -nt file2

file1 比 file2 新。

file1 -ot file2

file1 比 file2 老。

-d file

文件file存在,且是一个文件夹。

-e file

文件 file 存在。

-f file

文件file存在,且为普通文件。

-L file

文件file存在,且为符号连接。

-O file

文件 flle 存在, 且由有效用户ID拥有。

-r file

文件 flle 存在, 且是一个可读文件。

-s file

文件 flle 存在, 且长度大于0。

-w file

文件 flle 可写入。

-x file

文件 flle 可写执行。

可以使用man test查看那详细的说明。

当表达式为True时,测试命令返回退出状态 0,而表达式为False时返回退出状态1。

#!/bin/bash
FILE="/etc/resolv.conf"
if [ -e "$FILE" ]; then
  if [ -f "$FILE" ]; then
      echo "$FILE is a file."
  fi
  if [ -d "$FILE" ]; then
      echo "$FILE is a directory."
  fi
  if [ -r "$FILE" ]; then
      echo "$FILE is readable."
  fi
fi

字符串比较表达式表达式True

string1 = string2 或 string1 == string2

两字符相等

string1 != string2

两个字符串不相等

string1 > string2

string1 大于 string2.

string1 < string2

string1 小于string2.

-n string

字符串长度大于0

-z string

字符串长度等于0

#!/bin/bash
STRING=""
if [ -z "$STRING" ]; then
  echo "There is no string." >&2 
  exit 1
fi

# Output
# There is no string.

其中>&2将错误信息定位到标准错误输出。

数字比较表达式

下面这些是用来比较数字的一些表达式。

[…]((…))True

[ “int1” -eq “int2” ]

(( “int1” == “int2” ))

相等.

[ “int1” -nq “int2” ]

(( “int1” != “int2” ))

不等.

[ “int1” -lt “int2” ]

(( “int1” < “int2” ))

int2 大于 int1.

[ “int1” -le “int2” ]

(( “int1” “int2” ))

int1 大于 int2

[ “int1” -ge “int2” ]

(( “int1 >= “int2” ))

int1 大于等于 int2

双括号 (())

数值的比较或者计算可以用((... ))。

#!/bin/bash
a=3
b=4
c=3
if (("$a" < "$b")); then
    echo "$a is less than $b."
else
    echo "$a is not less than $b."
fi
if (("$a" != "$c")); then
    echo "$a is not equal to $c."
else
    echo "$a is equal to $c."
fi


# 计算
echo "$a + $b = $(($a + $b))"


# Output
# 3 is less than 4.
# 3 is equal to 3.
# 3 + 4 = 7

怎么使用 if/else 和 if/elif/else

其实上面已经展示了不少了,这里总结下if...else 和 if...elif...else 语句。

if/else 语句格式如下:

if [ condition-is-true ]
then
  command A
else
  command B
fi

# 或
if [ condition-is-true ]; then
  command A
else
  command B
fi

例如:

#!/bin/bash
MY_SHELL="csh"
if [ "$MY_SHELL" = "bash" ]
then
  echo "You are using the bash shell."
else
  echo "You are not using the bash shell."
fi

if/elif/else 语句格式如下:

if [ condition-is-true ]
then
  command A
elif [ condition-is-true ]
then
  command B
else
  command C
fi
# or
if [ condition-is-true ]; then
  command A
elif [ condition-is-true ]; then
  command B
else
  command C
fi

如:

#!/bin/bash
MY_SHELL="csh"
if [ "$MY_SHELL" = "bash" ]; then
  echo "You are using the bash shell."
elif [ "$MY_SHELL" = "csh" ]; then
  echo "You are using csh."
else
  echo "You are not using the bash shell."
fi

双中括号的使用[[]]

如用用于比较的变量不是单个单词,就需要[[]] , 或者用单中括号(这时需要加双引号)。 在平常的使用中,最好都使用[[]]。

与单中括号相比,双中括号具有其他功能。 如,可以对其中正则使用逻辑&&和||和=〜。

#!/bin/bash

VAR1="variable"
VAR2="variable 2"
if [[ (VAR1 == "variable")  ]]; then
    echo "They are the same."
else
    echo "Not the same."
fi

# 使用 &&
[[ ($VAR1 == variable) && (
$VAR2 == "variable 2") ]] && echo "They are the same again."

#!/bin/bash

digit=4
if [[ $digit =~ [0-9] ]]; then
    echo "$digit is a digit"
else
    echo "$digit isn't a digit"
fi
letter="abc"
if [[ $letter =~ [0-9] ]]; then
    echo "$letter is a digit"
else
    echo "$letter isn't a digit"
fi

# Output
# 4 is a digit
# abc isn't a digit

怎么使用 For 循环

for循环的使用如下:

for VARIABLE_NAME in ITEM_1 ITEM_N
do
  command A
done

例如:

#!/bin/bash
for COLOR in red green blue
do
  echo "COLOR: $COLOR"
done

# Output
# COLOR: red
# COLOR: green
# COLOR: blue

可以在其中使用变量,如下:

#!/bin/bash
COLORS="red green blue"
for COLOR in $COLORS
do
  echo "COLOR: $COLOR"
done

用 for 循环重命名文件

我们举个简单的例子,用for循环重命名当前目录下的jpg图片。

#!/bin/bash
IMGS=$(ls *jpg)
DATE=$(date +%F)
for IMG in $IMGS
do
  echo "Renaming ${IMG} to ${DATE}-${IMG}"
  mv ${IMG} ${DATE}-${IMG}
done

image-20210213170152011

怎么传参

执行脚本的时候,后面可以跟着很多参数,如:

$ scriptname param1 param2 param3

param1 到 param3 称为可选参数, 可以在脚本中用 $0, $1, $2等,来引用这些参赛。例如:

#!/bin/bash
echo "'\$0' is $0"
echo "'\$1' is $1"
echo "'\$2' is $2"
echo "'\$3' is $3"

输出:

$ ./param.sh
'$0' is ./param.sh
'$1' is
'$2' is
'$3' is

$0 参数0返回的是当前执行文件的名字,包括路径。

可以用 $@ 接受所以的参数。

#!/bin/bash
for PARAM in $@
do
  echo "Param is: $PARAM"
done

Using this script:

$ ./params.sh a b c d e f
Param is: a
Param is: b
Param is: c
Param is: d
Param is: e
Param is: f

怎么接收用户输入

用户输入称为STDIN。可以将read命令与-p(提示)选项一起使用来读取用户输入,它将输出提示字符串。 -r 选项不允许反斜杠转义任何字符。

read -rp "PROMPT" VARIABLE

例如:

#!/bin/bash
read -rp "Enter your programming languages: " PROGRAMMES
echo "Your programming languages are: "
for PROGRAMME in $PROGRAMMES; do
    echo "$PROGRAMME "
done

运行:

$ ./read.sh
Enter your programming languages: go py
Your programming languages are:
go
py

用大括号来表示范围 {}

如下所示,我们可以用大括号来表所一个数字或字母的范围。

$ echo {0..3}
$ echo {a..d}

# output: 
# 0 1 2 3
# a b c d

你也可以在 for 循环中这么使用:

#!/bin/bash
for i in {0..9}; 
do 
  touch file_"$i".txt; 
done

This will create different file names with different modification times.

$ ls -al file_*
-rw-rw-r-- 1 razeen razeen 0 2月  14 09:54 file_0.txt
-rw-rw-r-- 1 razeen razeen 0 2月  14 09:54 file_1.txt
-rw-rw-r-- 1 razeen razeen 0 2月  14 09:54 file_2.txt
...

怎么使用While

当 While 后的表达式结果为 true时,执行循环内语句。

#!/bin/bash
i=1
while [ $i -le 5 ]; do
  echo $i
  ((i++))
done

Output:

1
2
3
4
5

退出码/返回码 是什么?

每个命令都返回退出状态,范围为0-255。 0代表成功,非0代表错误。 可以用来进行错误检查。

数值含义

成功

返回内置命令,从而提示错误

126

命令找到了,但不是可执行的

127

没有找到命令

128+N

由于接收到信号N,命令退出

怎么检查退出码

特别声明:以上内容(如有图片或视频亦包括在内)为本平台用户上传并发布,本平台仅提供信息存储服务。


上篇:逆战官方网站

下篇:逆战 The Viral Factor

最新更新