shell的特殊符号及其意义
echo命令
Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。
• echo - 显示一行文本。传递到 echo 命令的任一个参数都会在(屏幕上)显示出来。
命令格式:
echo string
三种引号
- 在bash脚本中,有三种引号——单引号 ’ 2. 双引号 " 3. 反引号 `
- 单引号 两个单引号包围起来的字符串就是普通的字符串,它将保留原始的字面意思.
- 双引号 两个双引号包围起来的字符串,部分特殊字符将起到它们的作用. 这些特殊字符有: 美元符$, 反斜杠, 反引号, 感叹号!.
- 反引号 两个反引号包围起来的字符串,将作为命令来运行, 执行的输出结果作为该反引号的内容,称为命令替换, 它有另一种更好的写法: $(command)
#!
#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:
B
o
u
r
n
e
S
h
e
l
l
(
/
u
s
r
/
b
i
n
/
s
h
或
/
b
i
n
/
s
h
)
Bourne Shell(/usr/bin/sh或/bin/sh)
BourneShell(/usr/bin/sh或/bin/sh)
B
o
u
r
n
e
A
g
a
i
n
S
h
e
l
l
(
/
b
i
n
/
b
a
s
h
)
Bourne Again Shell(/bin/bash)
BourneAgainShell(/bin/bash)
C
S
h
e
l
l
(
/
u
s
r
/
b
i
n
/
c
s
h
)
C Shell(/usr/bin/csh)
CShell(/usr/bin/csh)
K
S
h
e
l
l
(
/
u
s
r
/
b
i
n
/
k
s
h
)
K Shell(/usr/bin/ksh)
KShell(/usr/bin/ksh)
S
h
e
l
l
f
o
r
R
o
o
t
(
/
s
b
i
n
/
s
h
)
Shell for Root(/sbin/sh)
ShellforRoot(/sbin/sh)
……
我们关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的Shell。
井号#
井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行。(#! 是例外)
如果被用在指令中,或者引号双引号括住的话,或者在倒斜线的后面,那他就变成一般符号,不具上述的特殊功能。
$
$ 与变量有关。先说说shell的变量:
定义变量
变量名不加美元符号($,PHP语言中变量需要),如:
my_name="abcd.abcd"
注意变量名和等号之间不能有空格。
使用变量–$
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
my_name="sir"
echo $your_name
echo ${your_name}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
如果不给skill变量加花括号,写成 echo “I am good at $skillScript” ,解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
可以说 $ 是取变量中内容符
$( )和反引号` `
在bash shell中,$( )与反引号 ` ` 都是用来做命令替换的。
反引号和 $( ) 的作用是一样的,在执行一条命令时,会先将其中的反引号或者 $( ) 中的语句当作命令执行一遍,再将结果加入原命令中重新执行。
在多层次的复合替换中, 反引号需要额外的跳脱处理 ( \` )处理,而 $( ) 则比较直观。
${ }
${ } —— 变量替换
${ } 用来作变量替换。一般情况下, $var 与 ${var} 并没有啥不一样。但是用 ${ } 会比较精确的界定变量名称的范围
除了变量替换,${ } 还有很多其他功能 —— 见下表:
一、
假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 . 及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 . 及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
项目 | Value |
---|---|
# | 是去掉左边(在鉴盘上 # 在 $ 之左边) |
% | 是去掉右边(在键盘上 % 在 $ 之右边) |
${file:0:5} | 提取最左边的 5 个字节:/dir1 |
${file:5:5} | 提取第 5 个字节右边的连续 5 个字节:/dir2 |
附 : | 单一符号是最小匹配﹔两个符号是最大匹配。 |
二、
我们也可以对变量值里的字符串作替换:
${file/dir/path}:将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部 dir 提换为 path:/path1/path2/path3/my.file.txt
三、
利用 ${ } 还可针对不同的变量状态赋值(没设定、空值、非空值):
${file-my.file.txt} :假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理)
${file:-my.file.txt} :假如 $file 没有设定或为空值,则使用 my.file.txt 作传回值。 (非空值时不作处理)
${file+my.file.txt} :假如 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(没设定时不作处理)
${file:+my.file.txt} :若 $file 为非空值,则使用 my.file.txt 作传回值。 (没设定及空值时不作处理)
${file=my.file.txt} :若 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (空值及非空值时不作处理)
${file:=my.file.txt} :若 $file 没设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (非空值时不作处理)
${file?my.file.txt} :若 $file 没设定,则将 my.file.txt 输出至 STDERR。 (空值及非空值时不作处理)
${file:?my.file.txt} :若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)
tips
以上的理解在于, 一定要分清楚 unset 与 null 及 non-null 这三种赋值状态.
一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连 null 也受影响.
${#var}
可计算出变量值的长度:
${#file}
可得到 27 ,因为 /dir1/dir2/dir3/my.file.txt
刚好是 27 个字节…
四、
用来处理数组:一般而言,A=“a b c def” 这样的变量只是将 $A 替换为一个单一的字符串,
但是改为 A=(a b c def) ,则是将 $A 定义为组数…
${A[@]} 或 ${A[*]} 可得到 a b c def (全部组数)
${A[0]} 可得到 a (第一个组数)
${A[1]} 则为第二个组数…
${#A[@]} 或 ${#A[*]} 可得到 4 (全部组数数量)
${#A[0]} 可得到 1 (即第一个组数(a)的长度),
${#A[3]} 可得到 3 (第四个组数(def)的长度)
A[3]=xyz 则是将第四个组数重新定义为 xyz …
$[ ] 与 $(())
$[ ]与$(())用途一致:用来作整数运算。
在 bash 中,$(( ))的整数运算符号大致有这些: \+ - * / % & | ^ ! AND、OR、XOR、NOT运算
注意
- 这种扩展计算是整数型的计算,不支持浮点型和字符串等。
- 若是逻辑判断,表达式为真则为1,假则为0。
[root@manager day5]# echo $((1>2))
0
[root@manager day5]# echo $((1<2))
1
[root@manager day5]# echo $[3>2]
1
$#、$*、$@、$?、$$、等
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
例子:
1——给脚本文件传递参数
编写下面的代码,并保存为 test.sh:
#!/bin/bash
echo "Process ID: $$"
echo "File Name: $0"
echo "First Parameter : $1"
echo "Second Parameter : $2"
echo "All parameters 1: $@"
echo "All parameters 2: $*"
echo "Total: $#"
运行 test.sh,并附带参数:
[mozhiyan@localhost demo]$ . ./test.sh Shell Linux
Process ID: 5943
File Name: bash
First Parameter : Shell
Second Parameter : Linux
All parameters 1: Shell Linux
All parameters 2: Shell Linux
Total: 2
2——给函数传递参数
编写下面的代码,并保存为 test.sh:
#!/bin/bash
#定义函数
function func(){
echo "Language: $1"
echo "URL: $2"
echo "First Parameter : $1"
echo "Second Parameter : $2"
echo "All parameters 1: $@"
echo "All parameters 2: $*"
echo "Total: $#"
}
#调用函数
func Java http://c.biancheng.net/java/
运行结果:
Language: Java
URL: http://c.biancheng.net/java/
First Parameter : Java
Second Parameter : http://c.biancheng.net/java/
All parameters 1: Java http://c.biancheng.net/java/
All parameters 2: Java http://c.biancheng.net/java/
Total: 2
( )和{ }:
相同点:
()和{}都是把一串的命令放在括号里面,如果命令在一行,则命令之间用;隔开
不同点:
1 ()只是把一串命令重新开一个子shell进行执行,不影响当前shell环境;
{}对一串命令在当前shell执行,影响当前shell环境
2 ()最后一个命令不用分号,{}最后一个命令要用分号
3 ()里的第一个命令和左边括号不必有空格,
{}的第一个命令和左括号之间必要要有一个空格
4 ()和{}中括号里面的某个命令的重定向只影响改名了,
但括号外的重定向则影响到括号里的所有命令
#()在子shell中执行,不影响当前shell环境
[root@www day4]# (pwd;cd /tmp;pwd)
/scripts/day4
/tmp
[root@www day4]#
#{}在当前shell执行,影响当前shell环境,并且命令左边有空格,命令最后有分号
[root@www day4]# { pwd;cd /tmp;pwd;}
/scripts/day4
/tmp
[root@www tmp]#
== 和=
- ==可用于判断变量是否相等,= 除了可用于判断变量是否相等外,还可以表示赋值。
- = 与 == 在 [ ] 中表示判断(字符串比较)时是等价的
- 在 (( )) 中 = 表示赋值, == 表示判断(整数比较),它们不等价
[root@manager day5]# s1="foo"
[root@manager day5]# s2="foo"
[root@manager day5]# [ $s1=$2 ] && echo "equal"
equal
[root@manager day5]# [ $s1==$2 ] && echo "equal"
equal
# = 与 == 在 [ ] 中表示判断(字符串比较)时是等价的
[root@manager day5]# ((n=5))
[root@manager day5]# echo $n
5
[root@manager day5]# ((n==5)) && echo "equal"
equal
#在 (( )) 中 = 表示赋值, == 表示判断(整数比较),它们不等价
参考链接: link1.