文章一览
- 前言
- 一、输入/输出及重定向命令
-
- [1.1 输入/输出命令](#1.1 输入/输出命令)
-
- [1.1.1 read命令](#1.1.1 read命令)
- [1.1.2 echo命令](#1.1.2 echo命令)
- [1.2 输入/输出重定向](#1.2 输入/输出重定向)
- [1.3 重定向深入讲解](#1.3 重定向深入讲解)
- [1.4 Here Document](#1.4 Here Document)
-
- [1.4.1 /dev/null 文件](#1.4.1 /dev/null 文件)
- 二、shell特殊字符和命令语法
-
- [2.1 引号](#2.1 引号)
-
- [2.1.1 双引号](#2.1.1 双引号)
- [2.1.2 单引号](#2.1.2 单引号)
- [2.1.3 倒引号](#2.1.3 倒引号)
- [2.2 注释、管道线和后台命令](#2.2 注释、管道线和后台命令)
- [2.3 命令执行操作符](#2.3 命令执行操作符)
- [2.4 复合命令](#2.4 复合命令)
- 三、shell脚本调试
-
- [3.1 解决环境设置问题](#3.1 解决环境设置问题)
- [3.2 解决脚本错误](#3.2 解决脚本错误)
- 四、文件包含
前言
在Shell编程中,重定向和特殊字符是非常重要的概念。它们允许我们控制输入和输出,并使我们能够构建复杂的脚本和命令。通过重定向和特殊字符,我们可以将命令的输出保存到文件中,从文件中读取输入,以及将多个命令连接在一起执行。这些功能极大地增强了Shell编程的灵活性和实用性。
重定向是将命令的输入或输出从默认位置改变到指定的位置的过程。在命令行中,我们可以使用特殊字符来指定要进行重定向的位置。例如,使用>字符将命令的输出重定向到文件中。这使得我们可以将命令的结果保存到文件中,而不是在终端上显示出来。类似地,使用<字符可以将文件中的内容重定向为命令的输入。这使得我们可以从文件中读取数据,而不是手动输入。此外,还可以使用>>字符将输出追加到文件中,而不是覆盖原有内容。
本篇文章将会讲解重定向 以及一些特殊字符与命令。
一、输入/输出及重定向命令
1.1 输入/输出命令
1.1.1 read命令
利用read命令从键盘上读取数据,然后赋给指定的变量。
一般格式: read [-u fd] [-n nchars] [name1 name2...]
变量个数M与输入数据N个数之间的关系:
例:(判断闰年与平年)
shell
#!/bin/bash
#determing if a year is a leap year
echo "Input a year number" #提示输入一个年号
read year #读取输入的年号
let "leap=year%4==0&&year%100!=0||year%400==0" #计算给定年号是闰年吗?
if [ $leap --eq 0 ] #若leap等于0,则不是闰年
then echo "$year is not a leap year. " #输出不是闰年信息
else echo " $year is a leap year. " #否则,输出闰年信息
fi
1.1.2 echo命令
显示其后的变量值或者直接显示它后面的字符串。
一般格式: echo [-neE] [arg...]
-e
选项代表不换行
shell
$ echo -e "Enter the file name ->\c"
Enter the file name ->$ ▌
这种形式与带"-n"选项的命令行功能相同:
-n
选项代表解释转义符
shell
$ echo -n "Enter the file name ->"
Enter the file name ->$ ▌
1.2 输入/输出重定向
1.输入重定向符
一般形式是:命令 < 文件名
让命令(或可执行程序)从指定文件中取得输入数据。例如:
\$ score < file1
注意:
bash
$ wc -l zhangyu
2 zhangyu
$ wc -l < zhangyu
2
上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。
2.输出重定向符
一般形式是:命令 > 文件名
把命令(或可执行程序)执行的结果输出到指定的文件。例如:
\$ who > abc
3.输出附加定向符
一般形式是: 命令>>文件名
把命令(或可执行程序)的输出附加到指定文件的后面,而该文件原有内容不被破坏。例如:
$ date>> file2
注意:需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
1.3 重定向深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
-
标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
-
标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
-
标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
command1 < infile > outfile
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
1.4 Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
bash
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
结尾的delimiter 一定要顶格 写,前面不能有任何字符 ,后面也不能有任何字符,包括空格和 tab 缩进。
开始的delimiter前后的空格会被忽略掉。
例
bash
wc -l << EOF
欢迎来到
章鱼大数据
www.ipieuvre.com
EOF
1.4.1 /dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
bash
command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
bash
command > /dev/null 2>&1
sudo apt-get update > /dev/null 2>&1
二、shell特殊字符和命令语法
2.1 引号
2.1.1 双引号
由双引号括起来的字符(除$、倒引号(`)和转义字符(\)外)均作为普通字符对待。
shell
$ cat exam9
echo "current directory is ` pwd ` " #倒引号表示命令替换
echo "home directory is $HOME" #以HOME的值代替$HOME
echo "file*.?" #其中的字符都作为普通字符出现
echo "directory '$HOME ' " #单引号仍作为普通字符出现
echo "Filename is No\$\* " #其中有转义字符
$ exam9
current directory is /home/ciee/dir1
home directory is /home/ciee
file*.?
directory '/home/ciee'
Filename is No$\*
2.1.2 单引号
由单引号括起来的所有字符都作为普通字符出现。例如:
shell
$ str=' echo "directory is $HOME" '
$ echo $str
echo "directory is $HOME "
2.1.3 倒引号
用倒引号括起来的字符串被shell解释为命令行。
可以将一个命令的执行结果赋给变量,即命令替换。
一般形式是:变量名=`命令表` 例如:dir=`pwd`
另一种形式是:变量名=(命令表) 例如:dir=(pwd)
shell
$ users=` who | wc -l `
$ echo The number of users is $users
The number of users is 3
$ Nuser=`echo The number of users is \` who | wc -l \` `
$ echo $Nuser
The number of users is 3
2.2 注释、管道线和后台命令
1.注释
-
shell程序中以"#"开头的正文行表示注释。
-
#! /bin/bash 说明该脚本是用Bourne Again shell编写的,应该调用相应的解释程序予以执行。
2.管道线
$ ls -l $HOME | wc --l
执行时,前一个命令的输出正好是下一个命令的输入。
$ ls | grep m?.c | wc --l
3.后台命令
$ gcc m1.c m2.c -o prog&
$
后台进程的调度优先级都低于前台进程的优先级。
2.3 命令执行操作符
1.顺序执行
各条命令之间以分号(;)隔开,从左到右依次执行。例如:
\$ pwd ; who | wc -l ; cd /home/bin
2.逻辑与
一般形式:命令1 && 命令2
先执行命令1,如果成功,才执行命令2;否则,不执行命令2。例如:
\$ cp ex1 ex10 && rm ex1
3.逻辑或
一般形式:命令1 || 命令2
先执行命令1,如果不成功,则执行命令2;否则,不执行命令2。例如:
$ cat abc || pwd
用&&或||可以把多个命令联系起来
2.4 复合命令
1.{ }形式
以{ }括起来的全部命令可视为语法上的一条命令,出现在管道符的一边 。成组命令的执行顺序是根据命令出现的先后次序 ,由左至右执行。
$ { echo "User Report for
date.";who; }
应注意,左括号"{"后面应有一个空格 ;右括号"}"之前应有一个分号(;)。
花括号也可以包含若干单独占一行的命令,例如:
shell
{ echo "Report of users for ` date ` . "
echo
echo "There are ` who | wc -l ` users logged in. "
echo
who | sort ; }
2.( )形式
shell
(echo "Current directory is ` pwd ` . "
cd /home/cieeqc ; ls -l ;
cp m1 em1 && rm m1
cat em1)
二者执行过程相同,但存在重要区别:{ }
成组命令只在本shell内执行命令表 ,不产生新的进程;而()
成组命令在新的子shell内执行,要建立新的子进程。
shell
$ a="current value "
$ echo $a
current value
$ ( a="new value-1 " ; echo $a )
new value-1 #(子shell内部a的值)
$ echo $a
current value # (与前者不同,这是外部a的值)
$ { a="new value-2 " ; echo $a ; }
new value-2 #(a的新值)
$ echo $a
new value-2 #(同一进程,a的值也相同)
$ pwd
/home/ciee /dir1
$ (cd /bin ; pwd ) #(在子shell中将工作目录改为/bin)
/bin
$ pwd
/home/ciee /dir1 #(仍是原来的目录,不受上面命令影响)
$ { cd /bin ; pwd ; }
/bin
$ pwd
/bin #(同一进程,前后关联)
三、shell脚本调试
3.1 解决环境设置问题
环境设置不对通常包括以下情况:
① 不能直接在其他shell下运行bash脚本。解决的办法是在脚本的第一行写上:#!/bin/bash。
② 在PATH环境变量中没有包括"."(当前目录)。解决办法是设置PATH:PATH=$PATH:.
③ 脚本文件与已存在命令的名字相同。
3.2 解决脚本错误
基本的错误类型有两种:语法错误 和逻辑错误。
- 语法错误是编写程序时违反了所用编程语言的规则而造成的。
- 逻辑错误通常是由于程序的逻辑关系存在问题。对此类问题需要进行程序调试。
调试技巧------设置x标志:
-
使用set -x命令:设置x标志后,执行下面命令前先显示该行的内容。
-
使用bash --x命令:在启动shell时,将它设置成跟踪模式。
四、文件包含
Shell和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
bash
. filename # 注意点号(.)和文件名中间有一空格
#或
source filename