使用exec

exec <filename命令会将stdin重定向到文件中. 从这句开始, 所有的stdin就都来自于这个文件了, 而不是标准输入(通常都是键盘输入). 这样就提供了一种按行读取文件的方法, 并且可以使用sed和/或awk来对每一行进行分析.

使用exec重定向stdin

1 #!/bin/bash
2 # 使用‘exec‘重定向stdin.
3
4
5 exec 6<&0 # 将文件描述符#6与stdin链接起来.
6 # 保存stdin.
7
8 exec < data-file # stdin被文件"data-file"所代替.
9
10 read a1 # 读取文件"data-file"的第一行.
11 read a2 # 读取文件"data-file"的第二行.
12
13 echo
14 echo "Following lines read from file."
15 echo "-------------------------------"
16 echo $a1
17 echo $a2
18
19 echo; echo; echo
20
21 exec 0<&6 6<&-22 #  现在将stdin从fd #6中恢复, 因为刚才我们把stdin重定向到#6了,
23 #+ 然后关闭fd #6 ( 6<&- ), 好让这个描述符继续被其他进程所使用.
24 #
25 # <&6 6<&-  这么做也可以.
26
27 echo -n "Enter data "
28 read b1 # 现在"read"已经恢复正常了, 就是能够正常的从stdin中读取.
29 echo "Input read from stdin."
30 echo "----------------------"
31 echo "b1 = $b1"
32
33 echo
34
35 exit 0

同样的, exec >filename命令将会把stdout重定向到一个指定的文件中. 这样所有命令的输出就都会发送到那个指定的文件, 而不是stdout.

exec N > filename会影响整个脚本或当前shell. 对于这个指定PID的脚本或shell来说,从这句命令执行之后, 就会重定向到这个文件中, 然而 . . .N > filename只会影响新fork出来的进程, 而不会影响整个脚本或shell.

使用exec来重定向stdout

1 #!/bin/bash
2 # reassign-stdout.sh
3
4 LOGFILE=logfile.txt
5
6 exec 6>&1 # 将fd #6与stdout链接起来.
7 # 保存stdout.
8
9 exec > $LOGFILE # stdout就被文件"logfile.txt"所代替了.
10
11 # ----------------------------------------------------------- #
12 # 在这块中所有命令的输出都会发送到文件$LOGFILE中.
13
14 echo -n "Logfile: "
15 date
16 echo "-------------------------------------"
17 echo
18
19 echo "Output of \"ls -al\" command"
20 echo
21 ls -al
22 echo; echo
23 echo "Output of \"df\" command"
24 echo
25 df
26
27 # ----------------------------------------------------------- #
28
29 exec 1>&6 6>&- # 恢复stdout, 然后关闭文件描述符#6.
30
31 echo
32 echo "== stdout now restored to default == "
33 echo
34 ls -al
35 echo
36
37 exit 0

使用exec在同一个脚本中重定向stdin和stdout

1 #!/bin/bash
2 # upperconv.sh
3 # 将一个指定的输入文件转换为大写.
4
5 E_FILE_ACCESS=70
6 E_WRONG_ARGS=71
7
8 if [ ! -r "$1" ] # 判断指定的输入文件是否可读?
9 then
10 echo "Can‘t read from input file!"
11 echo "Usage: $0 input-file output-file"
12 exit $E_FILE_ACCESS
13 fi #  即使输入文件($1)没被指定
14 #+ 也还是会以相同的错误退出(为什么?).
15
16 if [ -z "$2" ]
17 then
18 echo "Need to specify output file."
19 echo "Usage: $0 input-file output-file"
20 exit $E_WRONG_ARGS
21 fi
22
23
24 exec 4<&0
25 exec < $1 # 将会从输入文件中读取.
26
27 exec 7>&1
28 exec > $2 # 将写到输出文件中.
29 # 假设输出文件是可写的(添加检查?).
30
31 # -----------------------------------------------32 cat - | tr a-z A-Z # 转换为大写.
33 # ^^^^^ # 从stdin中读取.
34 # ^^^^^^^^^^ # 写到stdout上.
35 # 然而, stdin和stdout都被重定向了.
36 # -----------------------------------------------37
38 exec 1>&7 7>&- # 恢复stout.
39 exec 0<&4 4<&- # 恢复stdin.
40
41 # 恢复之后, 下边这行代码将会如预期的一样打印到stdout上.
42 echo "File \"$1\" written to \"$2\" as uppercase conversion."
43
44 exit 0

I/O重定向是一种避免可怕的子shell中不可访问变量问题的方法.

避免子shell

1 #!/bin/bash
2 # avoid-subshell.sh
3 # 由Matthew Walker所提出的建议.
4
5 Lines=0
6
7 echo
8
9 cat myfile.txt | while read line; # (译者注: 管道会产生子shell)
10 do {
11 echo $line
12 (( Lines++ )); #  增加这个变量的值
13 #+ 但是外部循环却不能访问.
14 #  子shell问题.
15 }
16 done
17
18 echo "Number of lines read = $Lines" # 0
19 # 错误!
20
21 echo "------------------------"
22
23
24 exec 3<> myfile.txt
25 while read line <&3
26 do {
27 echo "$line"
28 (( Lines++ )); #  增加这个变量的值
29 #+ 现在外部循环就可以访问了.
30 #  没有子shell, 现在就没问题了.
31 }
32 done
33 exec 3>&-34
35 echo "Number of lines read = $Lines" # 8
36
37 echo
38
39 exit 0
时间: 2024-10-19 13:52:09

使用exec的相关文章

shell中exec解析(转)

参考:<linux命令.编辑器与shell编程> <unix环境高级编程> exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息. bash shell的命令分为两类:外部命令和内部命令.外部命令是通过系统调用或独立的程序实现的,如sed.awk等等.内部命令是由特殊的文件格式(.def)所实现,如cd.history.exec等等. 在说明exe和source的区别之前

python的exec、eval详解

exec exec语句用来执行储存在字符串或文件中的Python语句.例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句.下面是一个简单的例子. exec 'print "Hello World"' 输出:Hello World 也可以实现赋值: a = 1 exec 'a = 2' 输出: 2 也可以在表达式后面通过in指定一个dictionary: dict = { 'a':1, 'b':2, 'c':3, 'd':4 } fun = ''

Docker exec与Docker attach

.. 声明: 本博客欢迎转发,但请保留原作者信息! 博客地址:http://blog.csdn.net/halcyonbaby 新浪微博:@寻觅神迹 内容系本人学习.研究和总结,如有雷同,实属荣幸! ================== Docker exec与Docker attach 不论是开发者是运维人员,都经常有需要进入容器的诉求. 目前看,主要的方法不外乎以下几种: 1. 使用ssh登陆进容器 2. 使用nsenter.nsinit等第三方工具 3. 使用docker本身提供的工具 方

linux下shell脚本执行方法及exec和source命令

exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息. bash shell的命令分为两类:外部命令和内部命令.外部命令是通过系统调用或独立的程序实现的,如sed.awk等等.内部命令是由特殊的文件格式(.def)所实现,如cd.history.exec等等. 在说明exe和source的区别之前,先说明一下fork的概念. fork是linux的系统调用,用来创建子进程(child

linux exec使用小结

一.exec 总结 exec命令 作用 exec ls 在shell中执行ls,ls结束后不返回原来的shell中了 exec <file file中的内容作为标准输入(替代STDIN) exec >file 将标准输出写入file(替代STDOUT) exec 3<file 将file读入到文件描述符3中(此时,创建了文件描述符3) sort <&3 将文件描述符3作为临时输入,用于sort排序 exec 4>file 将写入文件描述符4中的内容写入file中(此时

js正则表达式的match test exec replace函数

js正则表达式的方法:一种正则在前,一种正则在后: 使用: 1.exec var res = /\-[a-z]/g .exec("font-size"); console.log(res); 得到的结果: 所以返回的是一个数组,第一个为匹配值,第二个是匹配的位置,第三个是输入的数 2.test var res = /\-[a-z]/g .test("font-size");console.log(res); 返回为一个布尔值 3.match var res =(&q

-exec和xargs的区别

-exec和xargs的区别 2010-11-27 星期六 晴朗 当你在命令行执行: $find . -name 'core' -type f -exec rm {} /; 时,find -exec 命令会对每个匹配的文件执行一个单独的rm操作(execute a separate rm for each one), 正如你手动敲入下面命令: rm ./bin/core rm ./source/shopping_cart/core rm ./backups/core ... 但是使用这种方式,如

关于INSERT EXEC 语句不能嵌套的解决办法

一.问题  之前做项目的时候遇到过要在一个存储过程要操作另一个存储过程返回的结果集,想通过调用的存储过程保存到局部临时表进行操作.执行下面的sql,会提示: 消息 8164,级别 16,状态 1,过程 zryCreatePlantPlanningReport,第 27 行 INSERT EXEC 语句不能嵌套. 1 DROP TABLE #demo 2 CREATE TABLE #demo 3 ( 4 ZK_PLANNING_ID NVARCHAR(50), 5 ZK_PLAN_TITLE NV

Hive创建表格报【Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException】引发的血案

在成功启动Hive之后感慨这次终于没有出现Bug了,满怀信心地打了长长的创建表格的命令,结果现实再一次给了我一棒,报了以下的错误Error, return code 1 from org.apache.Hadoop.hive.ql.exec.DDLTask. MetaException,看了一下错误之后,先是楞了一下,接着我就发出感慨,自从踏上编程这条不归路之后,就没有一天不是在找Bug的路上就是在处理Bug,给自己贴了个标签:找Bug就跟吃饭一样的男人.抒发心中的感慨之后,该干活还是的干活.

Linux学习笔记(8)-exec族函数

昨天学习了Linux下的进程创建,创建一个进程的方法极为简单,只需要调用fork函数就可以创建出一个进程,但是-- 介绍fork()函数的时候提到,在创建进程后,子进程与父进程有相同的代码空间,执行的是和父进程完全一样的代码-- 那这样的话,我辛辛苦苦创建一个进程,还有什么意义? 辛辛苦苦的养大了一个儿子,难道就是为了让他走老子的老路? 带着满心的疑惑,我又进行了下一章的学习,突然恍然大悟,原来还有一个叫exec族函数的东西,专门就是用来给新创建的进程分配工作的. 调用exec族函数并不创建进程