Content #
# test.sh
echo $$
echo $0
第一种执行方式:
bash test.sh
15997 test.sh 第二种执行方式:
. test.sh
14642 bash
数组变量(Bash) \(*变量和\)@变量 特殊变量\(?和\)! 不同执行方式对$0的影响 向变量中已有的字符串尾部添加文本(Bash)
环境变量名何时使用$ env,printenv,set三个命令的区别 IFS环境变量
$cat test23
#!/bin/bash
# read file and create INSERT statements for MySQL
outfile='members.sql'
IFS=','
while read lname fname address city state zip
do
cat >> $outfile << EOF
INSERT INTO members (lname,fname,address,city,state,zip) VALUES
('$lname', '$fname', '$address', '$city', '$state', '$zip');
EOF
done < ${1}
$
脚本中出现了3处重定向操作。while循环使用read语句从数据文件中读取文本。注意在done语句中出现的重定向符号:
done < ${1}
当运行脚本test23时,$1代表第一个命令行参数,指明了待读取数据的文件。 read语句使用IFS字符解析读入的文本,这里将IFS指定为逗号。
脚本中另外两处重定向操作出现在同一条语句中:
cat >> $outfile << EOF
这条语句包含一个输出追加重定向(双大于号)和一个输入追加重定向(双小于号)。输出重定向将cat命令的输出追加到由$outfile变量指定的文件中。cat命令的输入不再取自标准输入,而是被重定向到脚本内部的数据。EOF符号标记了文件中的数据起止: INSERT INTO members (lname,fname,address,city,state,zip) VALUES (’$lname’, ‘$fname’, ‘$address’, ‘$city’, ‘$state’, ‘$zip’);
...在默认情况下,mktemp会在本地目录中创建一个文件。在使用mktemp命令时,只需指定一个文件名模板即可。模板可以包含任意文本字符,同时在文件名末尾要加上6个X:
$ mktemp testing.XXXXXX
$ ls -al testing*
-rw------- 1 rich rich 0 Jun 20 21:30 testing.UfIi13
$
mktemp命令会任意地将6个X替换为同等数量的字符,以保证文件名在目录中是唯一的。你可以创建多个临时文件,并确保每个文件名都不重复:
$ mktemp testing.XXXXXX
testing.1DRLuV
$ mktemp testing.XXXXXX
testing.lVBtkW
$ mktemp testing.XXXXXX
testing.PgqNKG
$ ls -l testing*
-rw------- 1 rich rich 0 Jun 20 21:57 testing.1DRLuV
-rw------- 1 rich rich 0 Jun 20 21:57 testing.PgqNKG
-rw------- 1 rich rich 0 Jun 20 21:30 testing.UfIi13
-rw------- 1 rich rich 0 Jun 20 21:57 testing.lVBtkW
$
Linux命令行与shell脚本编程大全
可以在输入重定向中将/dev/null作为输入文件。由于/dev/null文件不含任何内容,因此程序员通常用它来快速清除现有文件中的数据,这样就不用先删除文件再重新创建了:
$ cat testfile
This is the first line.
This is the second line.
This is the third line.
$ cat /dev/null > testfile
$ cat testfile
$
文件testfile仍然还在,但现在是一个空文件。这是清除日志文件的常用方法,因为日志文件必须时刻等待应用程序操作。
或者用cp命令
cp -f /dev/null /var/log/apache2/access.log
Linux命令行与shell脚本编程大全
有大量的命令行选项和参数可用于过滤lsof的输出。最常用的选项包括-p和-d,前者允许指定进程ID(PID),后者允许指定要显示的文件描述符编号(多个编号之间以逗号分隔)。
在打开了多个替代性文件描述符的脚本中,看一下使用lsof命令的结果:
$ cat test18
#!/bin/bash
# testing lsof with file descriptors
exec 3> test18file1
exec 6> test18file2
exec 7< testfile
/usr/sbin/lsof -a -p $$ -d0,1,2,3,6,7
$ ./test18
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
test18 3594 rich 0u CHR 136,0 2 /dev/pts/0
test18 3594 rich 1u CHR 136,0 2 /dev/pts/0
test18 3594 rich 2u CHR 136,0 2 /dev/pts/0
18 3594 rich 3w REG 253,0 0 360712 /home/rich/test18file1
18 3594 rich 6w REG 253,0 0 360715 /home/rich/test18file2
18 3594 rich 7r REG 253,0 73 360717 /home/rich/testfile
$
这个脚本创建了3个替代性文件描述符,两个用作输出(3和6),一个用作输入(7)。在脚本运行lsof命令时,你会在输出中看到新的文件描述符。我们去掉了输出中的第一部分,这样就能看到最终的文件名了。文件名显示了文件描述符所使用文件的完整路径。每个文件都显示为REG类型,说明这些是文件系统中的常规文件。
...如果创建了新的输入文件描述符或输出文件描述符,那么shell会在脚本退出时自动将其关闭。然而在一些情况下,需要在脚本结束前手动关闭文件描述符。
要关闭文件描述符,只需将其重定向到特殊符号&-即可。在脚本中如下所示:
exec 3>&-
该语句会关闭文件描述符3,不再在脚本中使用。
一旦关闭了文件描述符,就不能在脚本中向其写入任何数据,否则shell会发出错误消息。
在关闭文件描述符时还要注意另一件事。如果随后你在脚本中打开了同一个输出文件,那么shell就会用一个新文件来替换已有文件。这意味着如果你输出数据,它就会覆盖已有文件。
Linux命令行与shell脚本编程大全
可以打开单个文件描述符兼做输入和输出,这样就能用同一个文件描述符对文件进行读和写两种操作了。
但使用这种方法时要特别小心。由于这是对一个文件进行读和写两种操作,因此 shell会维护一个内部指针,指明该文件的当前位置。任何读或写都会从文件指针上次的位置开始。如果粗心的话,这会产生一些令人瞠目的结果。来看下面这个例子:
$ cat test16
#!/bin/bash
# testing input/output file descriptor
exec 3<> testfile
read line <&3
echo "Read: $line"
echo "This is a test line" >&3
$ cat testfile
This is the first line.
This is the second line.
This is the third line.
$ ./test16
Read: This is the first line.
$ cat testfile
This is the first line.
This is a test line
ine.
This is the third line.
$
在这个例子中,exec命令将文件描述符3用于文件testfile的读和写。接下来,使用分配好的文件描述符,通过read命令读取文件中的第一行,然后将其显示在 STDOUT中。最后,使用echo语句将一行数据写入由同一个文件描述符打开的文件中。
...