Liunx命令-从 shell 眼中看世界
-
echo - 显示一行文本
echo this is a test this is a test
-
echo * Desktop Documents ls-output.txt Music Pictures Public Templates Vide
为什么 echo 不打印”“呢?shell 在 echo 命 令被执行前把”“展开成了另外的东西(在这里,就是在当前工作目录下的文件名字)。 当回车键被按下时,shell 在命令被执行前在命令行上自动展开任何符合条件的字符, 所以 echo 命令的实际参数并不是”*“,而是它展开后的结果。
路径名展开
通配符所依赖的工作机制叫做路径名展开
echo D*
Desktop Documents
echo *s
Documents Pictures Templates Videos
echo [[:upper:]]*
Desktop Documents Music Pictures Public Templates Videos
echo /usr/*/share //查看家目录之外的目录
/usr/kerberos/share /usr/local/share
以圆点字符开头的文件名是隐藏文件。路径名展开也尊重这种 行为。echo *不会显示隐藏文件
如果展开模式以一个圆点开头,echo .我们就能够在展开中包含隐藏文件.然而,如果我们仔细检查一下输出结果,我们会看到名字”.” 和”…”也出现在结果中.我们可以通过这个命令来验证:
ls -d .* | less
为了在这种情况下正确地完成路径名展开,我们应该使用一个更精确的模式。 这个模式会正确地工作:
ls -d .[!.]?*
这种模式展开成所有以圆点开头,第二个字符不包含圆点,再包含至少一个字符, 并且这个字符之后紧接着任意多个字符的文件名。这个命令将正确列出大多数的隐藏文件 (但仍不能包含以多个圆点开头的文件名)
带有 -A 选项(“几乎所有”)的 ls 命令能够提供一份正确的隐藏文件清单:
ls -A
波浪线展开
波浪线字符(“~”)有特殊的含义。当它用在 一个单词的开头时,它会展开成指定用户的家目录名,如果没有指定用户名,则展开成当前用户的家目录:
echo ~
/home/me
算术表达式展开
shell 在展开中执行算数表达式。这允许我们把 shell 当作计算器来使用:
echo $((2 + 2))
4
算术表达式展开使用这种格式:括号中的表达式是指算术表达式,它由数值和算术操作符组成。算术表达式只支持整数(全部是数字,不带小数点)
$((expression))
一对括号可以用来把多个子表达式括起来
echo $(($((5**2)) * 3))
echo $(((5**2) * 3))
75
echo $(((5**2) * 3))
75
花括号展开
花括号表达式本身可 能包含一个由逗号分开的字符串列表,或者一个整数区间,或者单个的字符的区间。这种模式不能 嵌入空白字符。
echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
那这个有啥用呢?最常见的应用是,创建一系列的文件或目录列表。例如, 如果我们是摄影师,有大量的相片。我们想把这些相片按年月先后组织起来。首先, 我们要创建一系列以数值”年-月”形式命名的目录。通过这种方式,可以使目录名按照 年代顺序排列。
[me@linuxbox ~]$ mkdir Pics
[me@linuxbox ~]$ cd Pics
[me@linuxbox Pics]$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12}
[me@linuxbox Pics]$ ls
2007-01 2007-07 2008-01 2008-07 2009-01 2009-07
2007-02 2007-08 2008-02 2008-08 2009-02 2009-08
2007-03 2007-09 2008-03 2008-09 2009-03 2009-09
2007-04 2007-10 2008-04 2008-10 2009-04 2009-10
2007-05 2007-11 2008-05 2008-11 2009-05 2009-11
2007-06 2007-12 2008-06 2008-12 2009-06 2009-12
参数展开
例如,叫做”USER”的变量包含你的 用户名。可以这样做来调用参数,并查看 USER 中的内容,
echo $USER
me
要查看有效的变量列表,
printenv | less
在其它展开类型中,如果你误输入一个字符串,展开就不会发生。这时 echo 命令只简单地显示误键入的字符串。但在参数展开中,如果你拼写错了一个变量名, 展开仍然会进行,只是展开的结果是一个空字符串:
echo $SUER
命令替换
命令替换允许我们把一个命令的输出作为另一个命令的一部分来使用:
ls -l $(which cp)
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp
这里我们把 which cp 的执行结果作为一个参数传递给 ls 命令,因此可以在不知道 cp 命令 完整路径名的情况下得到它的文件属性列表。我们不只限于简单命令。也可以使用整个管道线 (只展示部分输出):
file $(ls /usr/bin/* | grep zip)
/usr/bin/bunzip2: symbolic link to `bzip2'
....
引用
我们已经知道 shell 有许多方式可以完成展开,现在是时候学习怎样来控制展开了
echo this is a test
this is a test
echo this is a test
this is a test
在第一个例子中,shell 利用单词分割删除掉 echo 命令的参数列表中多余的空格。在第二个例子中, 参数展开把 $1
的值替换为一个空字符串,因为 1
是没有定义的变量。shell 提供了一种 叫做引用的机制,来有选择地禁止不需要的展开。
双引号
使用双引号,我们可以处理包含空格的文件名。比方说 two words.txt 文件,如果我们试图在命令行中使用这个 文件,单词分割机制会导致这个文件名被看作两个独自的参数,而不是所期望 的单个参数:
ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory
使用双引号,我们可以阻止单词分割,得到期望的结果;
ls -l "two words.txt"
-rw-rw-r-- 1 me me 18 2008-02-20 13:03 two words.txt
记住,在双引号中,参数展开、算术表达式展开和命令替换仍然有效:
echo "$USER $((2+2)) $(cal)"
me 4 February 2008
Su Mo Tu We Th Fr Sa
....
在默认情况下,单词分割机制会在单词中寻找空格,制表符,和换行符,并把它们看作 单词之间的界定符。这意味着无引用的空格,制表符和换行符都不是文本的一部分, 它们只作为分隔符使用。
echo this is a test
this is a test
echo "this is a test"
this is a test
可以看到如果我们加上双引号,单词分割被禁止,内嵌的空格也不会被当作界定符,它们成为参数的一部分。
事实上,单词分割机制把换行符看作界定符,对命令替换产生了一个虽然微妙但有趣的影响。
echo $(cal)
February 2008 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
[me@linuxbox ~]$ echo "$(cal)"
February 2008
....
在第一个例子,没有引用的命令替换导致命令行包含38个参数。在第二个例子中, 命令行只有一个参数,参数中包括嵌入的空格和换行符。
单引号
如果需要禁止所有的展开,我们要使用单引号。
[me@linuxbox ~]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox ~]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox ~]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
转义字符
有时候我们只想引用单个字符。我们可以在字符之前加上一个反斜杠,在这里叫做转义字符。 经常在双引号中使用转义字符,来有选择地阻止展开。
echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00
为了允许反斜杠字符出现,输入”\“来转义。注意在单引号中,反斜杠失去它的特殊含义,它 被看作普通字符。echo 命令带上 ‘-e’ 选项,能够解释转义序列。你可以把转义序列放在 $’ ’ 里面。 以下例子中,我们可以使用 sleep 命令创建一个简单的倒数计数器
sleep 10; echo -e "Time's up\a"
sleep 10; echo "Time's up" $'\a'
反斜杠除了作为转义字符外,也可以构成一种表示法,来代表某种 特殊字符,这些特殊字符叫做控制码。ASCII 编码表中前32个字符被用来把命令转输到电报机 之类的设备。
转义序列 | 含义 |
---|---|
\a | 响铃(”警告”-导致计算机嘟嘟响) |
\b | 退格符 |
\n | 新的一行。在类 Unix 系统中,产生换行。 |
\r | 回车符 |
义 | |
-------- | -------------------------------------- |
\a | 响铃(”警告”-导致计算机嘟嘟响) |
\b | 退格符 |
\n | 新的一行。在类 Unix 系统中,产生换行。 |
\r | 回车符 |
\t | 制表符 |