改变linux shell的输出效果
[ 2009/12/15 16:14 | by selboo ]
echo -e "\033[32;49;1m [DONE] \033[39;49;0m"
输出结果 :[DONE]
把知识延伸下:(以下转载)
###########################
文本终端的颜色可以使用“ANSI非常规字符序列”来生成。举例:
echo -e "\033[44;37;5m ME \033[0m COOL"
以上命令设置背景成为蓝色,前景白色,闪烁光标,输出字符“ME”,然后重新设置屏幕到缺省设置,输出字符 “COOL”。“e”是命令 echo 的一个可选项,它用于激活特殊字符的解析器。“\033”引导非常规字符序列。“m”意味着设置属性然后结束非常规字符序列,这个例子里真正有效的字符是 “44;37;5” 和“0”。
修改“44;37;5”可以生成不同颜色的组合,数值和编码的前后顺序没有关系。可以选择的编码如下所示:
编码 颜色/动作
0 重新设置属性到缺省设置
1 设置粗体
2 设置一半亮度(模拟彩色显示器的颜色)
4 设置下划线(模拟彩色显示器的颜色)
5 设置闪烁
7 设置反向图象
22 设置一般密度
24 关闭下划线
25 关闭闪烁
27 关闭反向图象
30 设置黑色前景
31 设置红色前景
32 设置绿色前景
33 设置棕色前景
34 设置蓝色前景
35 设置紫色前景
36 设置青色前景
37 设置白色前景
38 在缺省的前景颜色上设置下划线
39 在缺省的前景颜色上关闭下划线
40 设置黑色背景
41 设置红色背景
42 设置绿色背景
43 设置棕色背景
44 设置蓝色背景
45 设置紫色背景
46 设置青色背景
47 设置白色背景
49 设置缺省黑色背景
其他有趣的代码还有:
\033[2J 清除屏幕
\033[0q 关闭所有的键盘指示灯
\033[1q 设置“滚动锁定”指示灯 (Scroll Lock)
\033[2q 设置“数值锁定”指示灯 (Num Lock)
\033[3q 设置“大写锁定”指示灯 (Caps Lock)
\033[15:40H 把关闭移动到第15行,40列
\007 发蜂鸣生beep
#######################
RedHat的字体和背景颜色的改变方法:
命令:
PS1="[\e[32;1m\u@\h \W]\\$"
或
export PS1="[\e[32;1m\u@\h \W]\\$" 两者的区别请查看环境变量的相关资料
解释:
\e[32;1m:这就是控制字体和背景颜色的转义字符,30~37是字体颜色、40~47是背景颜色
例子中的32;1m数字的位置是可以对调的如\e[1;32m,如果是在X环境下可以更换一下1的范围0~10,可能有的没用处:0或者不写(\e [0;32m或\e[;32m)显示浅颜色,1:显示高亮 4:加下划线.....如果改后的效果不好,但是又还原不了,那就不写m前面的数字,如\e[32;m,或者直接注销再登陆
\u \h \W:这是一些转义字符,下面详细解释:
\d :代表日期,格式为weekday month date,例如:"Mon Aug 1"
\H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
\h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
\t :显示时间为24小时格式,如:HH:MM:SS
\T :显示时间为12小时格式
\A :显示时间为24小时格式:HH:MM
\u :当前用户的账号名称
\v :BASH的版本信息
\w :完整的工作目录名称。家目录会以 ~代替
\W :利用basename取得工作目录名称,所以只会列出最后一个目录
\# :下达的第几个命令
\$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$
\n :新建一行
字体并不局限于一个颜色,可以有多个颜色:
PS1="[\e[32;1m\u@\e[35;1m\h \e[31;1m\W]\\$"
以上两个命令在注销后再登陆就失效了,用下面方法使其永久生效:
vi /etc/profile
在“export PATH .....”下面添加一行:export PS1="[\e[32;1m\u@\h \W]\\$"
注销再登陆,就成功了,如果没生效,使用source /etc/profile 命令试试,或者直接重启机器。
输出结果 :[DONE]
把知识延伸下:(以下转载)
###########################
文本终端的颜色可以使用“ANSI非常规字符序列”来生成。举例:
echo -e "\033[44;37;5m ME \033[0m COOL"
以上命令设置背景成为蓝色,前景白色,闪烁光标,输出字符“ME”,然后重新设置屏幕到缺省设置,输出字符 “COOL”。“e”是命令 echo 的一个可选项,它用于激活特殊字符的解析器。“\033”引导非常规字符序列。“m”意味着设置属性然后结束非常规字符序列,这个例子里真正有效的字符是 “44;37;5” 和“0”。
修改“44;37;5”可以生成不同颜色的组合,数值和编码的前后顺序没有关系。可以选择的编码如下所示:
编码 颜色/动作
0 重新设置属性到缺省设置
1 设置粗体
2 设置一半亮度(模拟彩色显示器的颜色)
4 设置下划线(模拟彩色显示器的颜色)
5 设置闪烁
7 设置反向图象
22 设置一般密度
24 关闭下划线
25 关闭闪烁
27 关闭反向图象
30 设置黑色前景
31 设置红色前景
32 设置绿色前景
33 设置棕色前景
34 设置蓝色前景
35 设置紫色前景
36 设置青色前景
37 设置白色前景
38 在缺省的前景颜色上设置下划线
39 在缺省的前景颜色上关闭下划线
40 设置黑色背景
41 设置红色背景
42 设置绿色背景
43 设置棕色背景
44 设置蓝色背景
45 设置紫色背景
46 设置青色背景
47 设置白色背景
49 设置缺省黑色背景
其他有趣的代码还有:
\033[2J 清除屏幕
\033[0q 关闭所有的键盘指示灯
\033[1q 设置“滚动锁定”指示灯 (Scroll Lock)
\033[2q 设置“数值锁定”指示灯 (Num Lock)
\033[3q 设置“大写锁定”指示灯 (Caps Lock)
\033[15:40H 把关闭移动到第15行,40列
\007 发蜂鸣生beep
#######################
RedHat的字体和背景颜色的改变方法:
命令:
PS1="[\e[32;1m\u@\h \W]\\$"
或
export PS1="[\e[32;1m\u@\h \W]\\$" 两者的区别请查看环境变量的相关资料
解释:
\e[32;1m:这就是控制字体和背景颜色的转义字符,30~37是字体颜色、40~47是背景颜色
例子中的32;1m数字的位置是可以对调的如\e[1;32m,如果是在X环境下可以更换一下1的范围0~10,可能有的没用处:0或者不写(\e [0;32m或\e[;32m)显示浅颜色,1:显示高亮 4:加下划线.....如果改后的效果不好,但是又还原不了,那就不写m前面的数字,如\e[32;m,或者直接注销再登陆
\u \h \W:这是一些转义字符,下面详细解释:
\d :代表日期,格式为weekday month date,例如:"Mon Aug 1"
\H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
\h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
\t :显示时间为24小时格式,如:HH:MM:SS
\T :显示时间为12小时格式
\A :显示时间为24小时格式:HH:MM
\u :当前用户的账号名称
\v :BASH的版本信息
\w :完整的工作目录名称。家目录会以 ~代替
\W :利用basename取得工作目录名称,所以只会列出最后一个目录
\# :下达的第几个命令
\$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$
\n :新建一行
字体并不局限于一个颜色,可以有多个颜色:
PS1="[\e[32;1m\u@\e[35;1m\h \e[31;1m\W]\\$"
以上两个命令在注销后再登陆就失效了,用下面方法使其永久生效:
vi /etc/profile
在“export PATH .....”下面添加一行:export PS1="[\e[32;1m\u@\h \W]\\$"
注销再登陆,就成功了,如果没生效,使用source /etc/profile 命令试试,或者直接重启机器。
linux批量修改文件名
[ 2009/12/13 11:49 | by selboo ]
使用 rename 命令
========================
NAME
rename - Rename files
SYNOPSIS
rename from to file...
========================
========================
NAME
rename - Rename files
SYNOPSIS
rename from to file...
========================
#! /bin/sh
INIFILE="./dirlist.ini"
CURPATH=$(pwd)
for SERVERPATH in $(cut -d: -f1 $INIFILE)
do
cd $SERVERPATH
cd ani
/usr/bin/rename .ANI .ani *
/usr/bin/rename .A?? .ani *
/usr/bin/rename .?N? .ani *
/usr/bin/rename .??I .ani *
cd ..
cd map
MAPPATH=$(pwd)
for maplist in $(ls -1)
do
cd ${MAPPATH}/${maplist}
/usr/bin/rename .yom .YOM *
/usr/bin/rename .y?? .YOM *
/usr/bin/rename .?o? .YOM *
/usr/bin/rename .??m .YOM *
done
cd $CURPATH
done
INIFILE="./dirlist.ini"
CURPATH=$(pwd)
for SERVERPATH in $(cut -d: -f1 $INIFILE)
do
cd $SERVERPATH
cd ani
/usr/bin/rename .ANI .ani *
/usr/bin/rename .A?? .ani *
/usr/bin/rename .?N? .ani *
/usr/bin/rename .??I .ani *
cd ..
cd map
MAPPATH=$(pwd)
for maplist in $(ls -1)
do
cd ${MAPPATH}/${maplist}
/usr/bin/rename .yom .YOM *
/usr/bin/rename .y?? .YOM *
/usr/bin/rename .?o? .YOM *
/usr/bin/rename .??m .YOM *
done
cd $CURPATH
done
Shell 管道及执行顺序
[ 2009/12/11 10:55 | by selboo ]
1、基本概念
a、I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;
b、常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor、monitor有关;
c、用 < 来改变读进的数据信道(stdin),使之从指定的档案读进;
d、用 > 来改变送出的数据信道(stdout, stderr),使之输出到指定的档案;
e、0 是 < 的默认值,因此 < 与 0<是一样的;同理,> 与 1> 是一样的;
f、在IO重定向 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料;
g、管道“|”(pipe line):上一个命令的 stdout 接到下一个命令的 stdin;
h、tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去;
i、bash(ksh)执行命令的过程:分析命令-变量求值-命令替代(``和$( ))-重定向-通配符展开-确定路径-执行命令;
j、( ) 将 command group 置于 sub-shell 去执行,也称 nested sub-shell,它有一点非常重要的特性是:继承父shell的Standard input, output, and error plus any other open file descriptors。
k、exec 命令:常用来替代当前 shell 并重新启动一个 shell,换句话说,并没有启动子 shell。使用这一命令时任何现有环境都将会被清除,。exec 在对文件描述符进行操作的时候,也只有在这时,exec 不会覆盖你当前的 shell 环境。
2、基本IO
cmd > file 把 stdout 重定向到 file 文件中
cmd >> file 把 stdout 重定向到 file 文件中(追加)
cmd 1> fiel 把 stdout 重定向到 file 文件中
cmd > file 2>&1 把 stdout 和 stderr 一起重定向到 file 文件中
cmd 2> file 把 stderr 重定向到 file 文件中
cmd 2>> file 把 stderr 重定向到 file 文件中(追加)
cmd >> file 2>&1 把 stderr 和 stderr 一起重定向到 file 文件中
cmd < file >file2 cmd 命令以 file 文件作为 stdin,以 file2 文件作为 stdout
cat <>file 以读写的方式打开 file
cmd < file cmd 命令以 file 文件作为 stdin
cmd << delimiter Here document,从 stdin 中读入,直至遇到delimiter 分界符
3、进阶IO
>&n 使用系统调用 dup (2) 复制文件描述符 n 并把结果用作标准输出
<&n 标准输入复制自文件描述符 n
<&- 关闭标准输入(键盘)
>&- 关闭标准输出
n<&- 表示将 n 号输入关闭
n>&- 表示将 n 号输出关闭
上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的 0 或 1。如:
... 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。
... 2>&1 运行一个命令并把它的标准输出和输出合并。(严格的说是通过复制文件描述符 1 来建立文件描述符 2 ,但效果通常是合并了两个流。)
2>&1说明:2>&1 也就是 FD2=FD1 ,这里并不是说FD2 的值 等于FD1的值,因为 > 是改变送出的数据信道,通俗的说是:把stderr并到stdout。
但使用类似 cmd 1>&3 这样的形式时,原理相同,但往往不同于 2>&1 和 1>&2 通常用来合并的作用。
注意:普通cmd命令的cmd n>&n 和exec n>&n 是有区别的。
exec 0 exec 1>outfilename # 打开文件outfilename作为stdout
exec 2>errfilename # 打开文件 errfilename作为 stderr
exec 0<&- # 关闭 FD0
exec 1>&- # 关闭 FD1
exec 5>&- # 关闭 FD5
问:
如果关闭了 FD0、FD1、FD2,其后果是什么?
恢复 FD0、FD1、FD2与 关闭FD0、FD1、FD2 有什么区别?代码分别是什么?
打开了FD3~FD9,我们用完之后,你觉得是将他们关闭还是恢复?
下面是提示(例子来源于CU):
exec 6>&2 2>ver # FD2(本来往monitor送的) 定向到文件ver
command >>dev/null & #丢弃FD1(stdout)
exec 2>&6 # 恢复 FD2
4、简单举例(其中 yes.txt存在,no.txt不存在)
a、stdout 和stderr 都通过管道送给egrep了:
(ls yes.txt 2>&1;ls no.txt 2>&1) 2>&1|egrep \* >file
(ls yes.txt;ls no.txt) 2>&1|egrep \* >file
###
这个例子就是让大家:理解 命令执行顺序 和 管道“|”
在命令执行前,先要进行重定向的处理,并将把 nested sub-shell 的stdout 接到 egrep 命令的 stdin。
nested sub-shell ,在 ( ) 中的两个命令可以看作一个命令。其 stdout(FD1) 通过 “|” 作为 egrep 的 stdin,再加上 2>&1 时,初始 stdout 和 stderr 都往管道 “|” 送。
###
b、没有任何东西通过管道送给egrep,全部送往monitor。
(ls yes.txt 2>&1;ls no.txt 2>&1) >&2|egrep \* >file
虽然在()里面将 FD2转往FD1,但在()外,遇到 >&2 ,结果所有的都送到monitor。
5、中阶例子(其中 you 这个文件是存在的,no 和 wu 这两个文件不存在)
r2007兄的:http://bbs.chinaunix.net/forum/viewtopic.php?t=221848&show_type=new&sid=cf30398c911e0d2b16313c6922123f67
条件:stderr通过管道送给egrep,正确消息仍然送给monitor(不变)
exec 4>&1;(ls you no 2>&1 1>&4 4>&-;ls wu 2>&1 1>&4 4>&-)|egrep \* >file;exec 4>&-
或者
exec 4>&1;(ls you no;ls wu) 2>&1 1>&4 4>&-|egrep \* >file;exec 4>&-
r2007 兄在其贴已有详细说明,如果加两个条件:
(1)要求cmd1和cmd2并行运行;
(2)将cmd1的返回值赋给变量 ss。
则为:
exec 3>&1;exec 4>&1
ss=$(((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file) 4>&1)
exec 3>&-;exec 4>&-
说明:
exec 3>&1;4>&1
### 建立FD3,是用来将下面ls那条语句(子shell)中的FD1 恢复到正常FD1,即输出到monitor,你可以把FD3看作最初始的FD1的硬盘备份(即输出到monitor);
### 建立FD4,到时用作保存ls的返回值(echo $?),你可以将FD4看作你考试时用于存放计算“echo $?”的草稿纸;
(ls you no 2>&1 1>&3 3>&-;echo $? >&4)
### 大家还记得前面说的子shell和管道吧。这条命令首先会继承FD0、FD1、FD2、FD3、FD4,它位于管道前,所以在运行命令前会先把子shell自己的FD1和管道“|”相连。
但是我们的条件是stderr通过管道送往egrep,stdout仍然输出到monitor。
于是通过2>&1,先把 子shell的FD1 的管道“送给”FD2,于是子shell中的stderr送往管道“|”;
再通过 1>&3,把以前的“硬盘备份”恢复给子shell的FD1,于是子shell中的FD1变成送到monitor了。
再通过3>&- ,将3关闭;
接着运行echo $? ,本来其输出值应该送往管道的,通过 >&4 ,将 输出 送往 “草稿纸”FD4,留以备用。
((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file)
于是,stderr 通过管道送给 egrep ,stdout 送给monitor,但是,还有 FD4,它送到哪去了?
$(((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file) 4>&1)
最后的 4>&1 ,就是把FD4 重定向到 FD1。但由于其输出在 $( )中,其值就赋给变量ss了。
最后一行关闭 FD3、FD4。
6、高阶例子
lightspeed 版主大大的:Shell 经典问题之 [ I/O 重定向] (http://bbs.chinaunix.net/forum/viewtopic.php?t=452079&show_type=new)
[Q] 对于命令 cmd1, cmd2, cmd3, cmd4. 如何利用单向管道完成下列功能:
1. 所有命令并行执行
2. cmd1 和 cmd2 不需要 stdin
3. cmd1 和 cmd2 的 stdout 定向到 cmd3 的 stdin
4. cmd1 和 cmd2 的 stderr 定向到 cmd4 的 stdin
5. cmd3 的 stdout 定向到文件 a, stderr 定向到屏幕
6. cmd4 的 stdout 定向到文件 b, stderr 定向到屏幕
7. cmd1 的返回码赋给变量 s
8. 不能利用临时文件
解决方法:
exec 3>&1; exec 4>&1
my_value=$(((((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1 | cmd4 >b ) 4>&1)
exec 3>&-; exec 4>&-
解释:
exec 3>&1; exec 4>&1
建立FD3 ,给cmd1恢复其FD1用和给cmd3 恢复其FD2用;
建立FD4,保存“echo $?”输出值的“草稿纸”
第一对括号到第一个管道:(cmd1 1>&3 ; echo $? >&4 )|
cmd1本身没有stdin,其stdout原要送往第一个管道,由于1>&3的作用,其stdout被送往FD3;而 >&4 的作用实际是将 cmd1 运行后的返回码送往 FD4。cmd1的stderr默认等待下一步处理。最后,没有往管道送任何东西;
第二对括号到第二个管道:((cmd1 1>&3 ; echo $? >&4 )| cmd2) 3>&1|
由于第一个括号中cmd1的 stdout 被送往 FD3,导致管道左端没有任何输入,cmd2 从而就没有stdin。cmd2 的stdout则为默认的;
将第二对括号看出一个命令,其所有的stdout送往第二个管道“|”;同时由于3>&1的作用,原先cmd1的stdout在送往FD3 又与cmd2的stdout并到一起,所以cmd1 和 cmd2 的 stdout 都送往第二个管道“|”。而cmd1、cmd2的stderr仍然默认等待下一步处理;
第三对括号到第三个管道:(((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1|
cmd3 >a 2>&3:cmd3接收处理来自管道的stdin后,其 stdout 送给文件a,其stderr送往FD3,由于FD3继承FD1,实际上其stderr是送往monitor。如果没有“2>&3”,那么cmd3的stderr就会干扰cmd1和cmd2的错误输出,所以它是必须的;
将第三个括号里完全看作一个命令,其stdout送往管道 “|”,由于2>&1,于是stderr也送往着管道。但由于cmd1、cmd2的stdout已经送给了cmd3处理,而cmd3的stdout输出到文件a,cmd3的stderr也送往monitor,所以实际上只有cmd1和cmd2的stderr送往管道。
cmd4 >b:cmd4接收处理来自管道的stdin后,其stdout 定向到文件 b,stderr 默认输出到monitor。
第四对括号:( (((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1| cmd4 >b ) 4>&1
四对括号里面所有命令的 FD1、FD2都处理完了,但是还有“echo $? >&4”没处理。“4>&1”的作用就是“将FD4并到stdout”,但由于其他命令的stdout都处理完了,实际上就只有 $? 的值。
又由于 $() 会建立一个管道,输入端为()内命令,故 $? 的值被赋给变量 my_value。
最后一行是关闭FD3和FD4。
另:恢复重定向或关闭的stdout:exec 1>&2 ,恢复重定向或关闭的stderr:exec 2>&1。如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:exec 1>/dev/tty 恢复。
++++++++++++++++++++++++++++++++++++++++++++
我尝试回答下面的问题。如有错误,还请各位前辈指正!
7、在一个交互式的(Interactive) shell 中, 用 exec 进行 I/O 重定向.
1). Stdin, stderr 可以定向到文件中吗? 有什么结果?
a、在交互式shell中,可以将stdin定向到文件。执行:exec 0 结果为:in 文件中每一行均会被自动执行,并且在最后会再加执行一个 exit 命令,导致退出(或退回到正常shell下)。
如 in 文件内容:$ more in
date
read lsp
echo hahha
echo "this is $lsp"
在提示符下执行命令:$ exec 0 $ date
Tue Jan 18 18:29:07 HKT 2005
$ read lsp # 其下面本应有的那句“ echo hahha ”的 “hahaha” 已经被读入到变量 lsp 中了
$ echo "this is $lsp"
this is echo hahha
$ exit
b、在交互式shell中,可以将stderr定向到文件。执行:exec 2>err
结果为:命令提示符PS被屏蔽,输入的命令也被屏蔽。但是命令执行的结果,如果是stdout 则会回显到屏幕上,如果是 stderr 则不会回显到屏幕上。其中,命令提示符、命令、stderr均会保存到文件 err 中。如:
$ exec 2>err
err in out # 执行 ls 命令
Tue Jan 18 18:55:58 HKT 2005 # 执行 date 命令,而后执行了“ ls nofile”,nofile这个文件不存在
$ # 执行 exit 命令
现在让我们查看 err文件:
$ more err
[lsp@ii lsp]$ ls
[lsp@ii lsp]$ date
[lsp@ii lsp]$ ls nofile
ls: nofile: No such file or directory
[lsp@ii lsp]$ exit
exit
c、在交互式shell中,可以将stdout定向到文件。这个使我们常用到的。就不说了。就是将错误的输出内容定向到文件中。正确的输出内容并不受影响。
2). Stdin, Stderr 可以关闭吗? 有什么结果?
在交互式shell中,如果关闭stdin,如:exec 0<&- ,其结果是退出(或退回到正常shell下)。
在交互式shell中,如果关闭stderr,如:exec 2>&- ,状态同stderr定向到文件,唯一不同的是没有保存下来。
在交互式shell中,如果关闭stdoutr,如:exec 1>&- ,只要执行有stdout或stderr内容送往 monitor 的命令,如ls、date这类命令,均会报错:“ls: write error: Bad file descriptor”。其他如cd、mkdir、……这类命令不受影响。
3). 如果 stdin, stdout, stderr 进行了重定向或关闭, 但没有保存原来的 FD, 可以将其恢复到 default 状态吗?
*** 如果关闭了stdin,因为会导致退出,那肯定不能恢复。
*** 如果重定向或关闭 stdout和stderr其中之一,可以恢复,因为他们默认均是送往monitor(但不知会否有其他影响)。如恢复重定向或关闭的stdout:exec 1>&2 ,恢复重定向或关闭的stderr:exec 2>&1。
*** 如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:exec 1>/dev/tty 恢复。
+++++++++++++++++++
下面参考了 r2007 兄的回复!谨以致谢!
+++++++++++++++++++
8、cmd >a 2>a 和 cmd >a 2>&1 为什么不同?
cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖。
cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。
他们的不同点在于:
cmd >a 2>a 相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;
而cmd >a 2>&1 只使用了一个管道FD1,但已经包括了stdout和stderr。
从IO效率上来讲,cmd >a 2>&1的效率更高。
a、I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;
b、常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor、monitor有关;
c、用 < 来改变读进的数据信道(stdin),使之从指定的档案读进;
d、用 > 来改变送出的数据信道(stdout, stderr),使之输出到指定的档案;
e、0 是 < 的默认值,因此 < 与 0<是一样的;同理,> 与 1> 是一样的;
f、在IO重定向 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料;
g、管道“|”(pipe line):上一个命令的 stdout 接到下一个命令的 stdin;
h、tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去;
i、bash(ksh)执行命令的过程:分析命令-变量求值-命令替代(``和$( ))-重定向-通配符展开-确定路径-执行命令;
j、( ) 将 command group 置于 sub-shell 去执行,也称 nested sub-shell,它有一点非常重要的特性是:继承父shell的Standard input, output, and error plus any other open file descriptors。
k、exec 命令:常用来替代当前 shell 并重新启动一个 shell,换句话说,并没有启动子 shell。使用这一命令时任何现有环境都将会被清除,。exec 在对文件描述符进行操作的时候,也只有在这时,exec 不会覆盖你当前的 shell 环境。
2、基本IO
cmd > file 把 stdout 重定向到 file 文件中
cmd >> file 把 stdout 重定向到 file 文件中(追加)
cmd 1> fiel 把 stdout 重定向到 file 文件中
cmd > file 2>&1 把 stdout 和 stderr 一起重定向到 file 文件中
cmd 2> file 把 stderr 重定向到 file 文件中
cmd 2>> file 把 stderr 重定向到 file 文件中(追加)
cmd >> file 2>&1 把 stderr 和 stderr 一起重定向到 file 文件中
cmd < file >file2 cmd 命令以 file 文件作为 stdin,以 file2 文件作为 stdout
cat <>file 以读写的方式打开 file
cmd < file cmd 命令以 file 文件作为 stdin
cmd << delimiter Here document,从 stdin 中读入,直至遇到delimiter 分界符
3、进阶IO
>&n 使用系统调用 dup (2) 复制文件描述符 n 并把结果用作标准输出
<&n 标准输入复制自文件描述符 n
<&- 关闭标准输入(键盘)
>&- 关闭标准输出
n<&- 表示将 n 号输入关闭
n>&- 表示将 n 号输出关闭
上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的 0 或 1。如:
... 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。
... 2>&1 运行一个命令并把它的标准输出和输出合并。(严格的说是通过复制文件描述符 1 来建立文件描述符 2 ,但效果通常是合并了两个流。)
2>&1说明:2>&1 也就是 FD2=FD1 ,这里并不是说FD2 的值 等于FD1的值,因为 > 是改变送出的数据信道,通俗的说是:把stderr并到stdout。
但使用类似 cmd 1>&3 这样的形式时,原理相同,但往往不同于 2>&1 和 1>&2 通常用来合并的作用。
注意:普通cmd命令的cmd n>&n 和exec n>&n 是有区别的。
exec 0 exec 1>outfilename # 打开文件outfilename作为stdout
exec 2>errfilename # 打开文件 errfilename作为 stderr
exec 0<&- # 关闭 FD0
exec 1>&- # 关闭 FD1
exec 5>&- # 关闭 FD5
问:
如果关闭了 FD0、FD1、FD2,其后果是什么?
恢复 FD0、FD1、FD2与 关闭FD0、FD1、FD2 有什么区别?代码分别是什么?
打开了FD3~FD9,我们用完之后,你觉得是将他们关闭还是恢复?
下面是提示(例子来源于CU):
exec 6>&2 2>ver # FD2(本来往monitor送的) 定向到文件ver
command >>dev/null & #丢弃FD1(stdout)
exec 2>&6 # 恢复 FD2
4、简单举例(其中 yes.txt存在,no.txt不存在)
a、stdout 和stderr 都通过管道送给egrep了:
(ls yes.txt 2>&1;ls no.txt 2>&1) 2>&1|egrep \* >file
(ls yes.txt;ls no.txt) 2>&1|egrep \* >file
###
这个例子就是让大家:理解 命令执行顺序 和 管道“|”
在命令执行前,先要进行重定向的处理,并将把 nested sub-shell 的stdout 接到 egrep 命令的 stdin。
nested sub-shell ,在 ( ) 中的两个命令可以看作一个命令。其 stdout(FD1) 通过 “|” 作为 egrep 的 stdin,再加上 2>&1 时,初始 stdout 和 stderr 都往管道 “|” 送。
###
b、没有任何东西通过管道送给egrep,全部送往monitor。
(ls yes.txt 2>&1;ls no.txt 2>&1) >&2|egrep \* >file
虽然在()里面将 FD2转往FD1,但在()外,遇到 >&2 ,结果所有的都送到monitor。
5、中阶例子(其中 you 这个文件是存在的,no 和 wu 这两个文件不存在)
r2007兄的:http://bbs.chinaunix.net/forum/viewtopic.php?t=221848&show_type=new&sid=cf30398c911e0d2b16313c6922123f67
条件:stderr通过管道送给egrep,正确消息仍然送给monitor(不变)
exec 4>&1;(ls you no 2>&1 1>&4 4>&-;ls wu 2>&1 1>&4 4>&-)|egrep \* >file;exec 4>&-
或者
exec 4>&1;(ls you no;ls wu) 2>&1 1>&4 4>&-|egrep \* >file;exec 4>&-
r2007 兄在其贴已有详细说明,如果加两个条件:
(1)要求cmd1和cmd2并行运行;
(2)将cmd1的返回值赋给变量 ss。
则为:
exec 3>&1;exec 4>&1
ss=$(((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file) 4>&1)
exec 3>&-;exec 4>&-
说明:
exec 3>&1;4>&1
### 建立FD3,是用来将下面ls那条语句(子shell)中的FD1 恢复到正常FD1,即输出到monitor,你可以把FD3看作最初始的FD1的硬盘备份(即输出到monitor);
### 建立FD4,到时用作保存ls的返回值(echo $?),你可以将FD4看作你考试时用于存放计算“echo $?”的草稿纸;
(ls you no 2>&1 1>&3 3>&-;echo $? >&4)
### 大家还记得前面说的子shell和管道吧。这条命令首先会继承FD0、FD1、FD2、FD3、FD4,它位于管道前,所以在运行命令前会先把子shell自己的FD1和管道“|”相连。
但是我们的条件是stderr通过管道送往egrep,stdout仍然输出到monitor。
于是通过2>&1,先把 子shell的FD1 的管道“送给”FD2,于是子shell中的stderr送往管道“|”;
再通过 1>&3,把以前的“硬盘备份”恢复给子shell的FD1,于是子shell中的FD1变成送到monitor了。
再通过3>&- ,将3关闭;
接着运行echo $? ,本来其输出值应该送往管道的,通过 >&4 ,将 输出 送往 “草稿纸”FD4,留以备用。
((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file)
于是,stderr 通过管道送给 egrep ,stdout 送给monitor,但是,还有 FD4,它送到哪去了?
$(((ls you no 2>&1 1>&3 3>&-;echo $? >&4)|egrep \* >file) 4>&1)
最后的 4>&1 ,就是把FD4 重定向到 FD1。但由于其输出在 $( )中,其值就赋给变量ss了。
最后一行关闭 FD3、FD4。
6、高阶例子
lightspeed 版主大大的:Shell 经典问题之 [ I/O 重定向] (http://bbs.chinaunix.net/forum/viewtopic.php?t=452079&show_type=new)
[Q] 对于命令 cmd1, cmd2, cmd3, cmd4. 如何利用单向管道完成下列功能:
1. 所有命令并行执行
2. cmd1 和 cmd2 不需要 stdin
3. cmd1 和 cmd2 的 stdout 定向到 cmd3 的 stdin
4. cmd1 和 cmd2 的 stderr 定向到 cmd4 的 stdin
5. cmd3 的 stdout 定向到文件 a, stderr 定向到屏幕
6. cmd4 的 stdout 定向到文件 b, stderr 定向到屏幕
7. cmd1 的返回码赋给变量 s
8. 不能利用临时文件
解决方法:
exec 3>&1; exec 4>&1
my_value=$(((((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1 | cmd4 >b ) 4>&1)
exec 3>&-; exec 4>&-
解释:
exec 3>&1; exec 4>&1
建立FD3 ,给cmd1恢复其FD1用和给cmd3 恢复其FD2用;
建立FD4,保存“echo $?”输出值的“草稿纸”
第一对括号到第一个管道:(cmd1 1>&3 ; echo $? >&4 )|
cmd1本身没有stdin,其stdout原要送往第一个管道,由于1>&3的作用,其stdout被送往FD3;而 >&4 的作用实际是将 cmd1 运行后的返回码送往 FD4。cmd1的stderr默认等待下一步处理。最后,没有往管道送任何东西;
第二对括号到第二个管道:((cmd1 1>&3 ; echo $? >&4 )| cmd2) 3>&1|
由于第一个括号中cmd1的 stdout 被送往 FD3,导致管道左端没有任何输入,cmd2 从而就没有stdin。cmd2 的stdout则为默认的;
将第二对括号看出一个命令,其所有的stdout送往第二个管道“|”;同时由于3>&1的作用,原先cmd1的stdout在送往FD3 又与cmd2的stdout并到一起,所以cmd1 和 cmd2 的 stdout 都送往第二个管道“|”。而cmd1、cmd2的stderr仍然默认等待下一步处理;
第三对括号到第三个管道:(((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1|
cmd3 >a 2>&3:cmd3接收处理来自管道的stdin后,其 stdout 送给文件a,其stderr送往FD3,由于FD3继承FD1,实际上其stderr是送往monitor。如果没有“2>&3”,那么cmd3的stderr就会干扰cmd1和cmd2的错误输出,所以它是必须的;
将第三个括号里完全看作一个命令,其stdout送往管道 “|”,由于2>&1,于是stderr也送往着管道。但由于cmd1、cmd2的stdout已经送给了cmd3处理,而cmd3的stdout输出到文件a,cmd3的stderr也送往monitor,所以实际上只有cmd1和cmd2的stderr送往管道。
cmd4 >b:cmd4接收处理来自管道的stdin后,其stdout 定向到文件 b,stderr 默认输出到monitor。
第四对括号:( (((cmd1 1>&3 ; echo $? >&4 )| cmd2 ) 3>&1 | cmd3 >a 2>&3 ) 2>&1| cmd4 >b ) 4>&1
四对括号里面所有命令的 FD1、FD2都处理完了,但是还有“echo $? >&4”没处理。“4>&1”的作用就是“将FD4并到stdout”,但由于其他命令的stdout都处理完了,实际上就只有 $? 的值。
又由于 $() 会建立一个管道,输入端为()内命令,故 $? 的值被赋给变量 my_value。
最后一行是关闭FD3和FD4。
另:恢复重定向或关闭的stdout:exec 1>&2 ,恢复重定向或关闭的stderr:exec 2>&1。如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:exec 1>/dev/tty 恢复。
++++++++++++++++++++++++++++++++++++++++++++
我尝试回答下面的问题。如有错误,还请各位前辈指正!
7、在一个交互式的(Interactive) shell 中, 用 exec 进行 I/O 重定向.
1). Stdin, stderr 可以定向到文件中吗? 有什么结果?
a、在交互式shell中,可以将stdin定向到文件。执行:exec 0 结果为:in 文件中每一行均会被自动执行,并且在最后会再加执行一个 exit 命令,导致退出(或退回到正常shell下)。
如 in 文件内容:$ more in
date
read lsp
echo hahha
echo "this is $lsp"
在提示符下执行命令:$ exec 0 $ date
Tue Jan 18 18:29:07 HKT 2005
$ read lsp # 其下面本应有的那句“ echo hahha ”的 “hahaha” 已经被读入到变量 lsp 中了
$ echo "this is $lsp"
this is echo hahha
$ exit
b、在交互式shell中,可以将stderr定向到文件。执行:exec 2>err
结果为:命令提示符PS被屏蔽,输入的命令也被屏蔽。但是命令执行的结果,如果是stdout 则会回显到屏幕上,如果是 stderr 则不会回显到屏幕上。其中,命令提示符、命令、stderr均会保存到文件 err 中。如:
$ exec 2>err
err in out # 执行 ls 命令
Tue Jan 18 18:55:58 HKT 2005 # 执行 date 命令,而后执行了“ ls nofile”,nofile这个文件不存在
$ # 执行 exit 命令
现在让我们查看 err文件:
$ more err
[lsp@ii lsp]$ ls
[lsp@ii lsp]$ date
[lsp@ii lsp]$ ls nofile
ls: nofile: No such file or directory
[lsp@ii lsp]$ exit
exit
c、在交互式shell中,可以将stdout定向到文件。这个使我们常用到的。就不说了。就是将错误的输出内容定向到文件中。正确的输出内容并不受影响。
2). Stdin, Stderr 可以关闭吗? 有什么结果?
在交互式shell中,如果关闭stdin,如:exec 0<&- ,其结果是退出(或退回到正常shell下)。
在交互式shell中,如果关闭stderr,如:exec 2>&- ,状态同stderr定向到文件,唯一不同的是没有保存下来。
在交互式shell中,如果关闭stdoutr,如:exec 1>&- ,只要执行有stdout或stderr内容送往 monitor 的命令,如ls、date这类命令,均会报错:“ls: write error: Bad file descriptor”。其他如cd、mkdir、……这类命令不受影响。
3). 如果 stdin, stdout, stderr 进行了重定向或关闭, 但没有保存原来的 FD, 可以将其恢复到 default 状态吗?
*** 如果关闭了stdin,因为会导致退出,那肯定不能恢复。
*** 如果重定向或关闭 stdout和stderr其中之一,可以恢复,因为他们默认均是送往monitor(但不知会否有其他影响)。如恢复重定向或关闭的stdout:exec 1>&2 ,恢复重定向或关闭的stderr:exec 2>&1。
*** 如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:exec 1>/dev/tty 恢复。
+++++++++++++++++++
下面参考了 r2007 兄的回复!谨以致谢!
+++++++++++++++++++
8、cmd >a 2>a 和 cmd >a 2>&1 为什么不同?
cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖。
cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。
他们的不同点在于:
cmd >a 2>a 相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;
而cmd >a 2>&1 只使用了一个管道FD1,但已经包括了stdout和stderr。
从IO效率上来讲,cmd >a 2>&1的效率更高。
Linux SHELL if 命令参数说明
[ 2009/11/30 14:08 | by selboo ]
* -b 当file存在并且是块文件时返回真
* -c 当file存在并且是字符文件时返回真
* -d 当pathname存在并且是一个目录时返回真
* -e 当pathname指定的文件或目录存在时返回真
* -f 当file存在并且是正规文件时返回真
* -g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真
* -h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效
* -k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真
* -p 当file存在并且是命令管道时返回为真
* -r 当由pathname指定的文件或目录存在并且可读时返回为真
* -s 当file存在文件大小大于0时返回真
* -u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真
* -w 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。
* -o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真。
UNIX Shell 里面比较字符写法:
* -eq 等于
* -ne 不等于
* -gt 大于
* -lt 小于
* -le 小于等于
* -ge 大于等于
* -z 空串
* = 两个字符相等
* != 两个字符不等
* -n 非空串
* -c 当file存在并且是字符文件时返回真
* -d 当pathname存在并且是一个目录时返回真
* -e 当pathname指定的文件或目录存在时返回真
* -f 当file存在并且是正规文件时返回真
* -g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真
* -h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效
* -k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真
* -p 当file存在并且是命令管道时返回为真
* -r 当由pathname指定的文件或目录存在并且可读时返回为真
* -s 当file存在文件大小大于0时返回真
* -u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真
* -w 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。
* -o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真。
UNIX Shell 里面比较字符写法:
* -eq 等于
* -ne 不等于
* -gt 大于
* -lt 小于
* -le 小于等于
* -ge 大于等于
* -z 空串
* = 两个字符相等
* != 两个字符不等
* -n 非空串
1.练习文件
cat datafile
northwest NW Charles Main 3.0 .98 3 34
northern WE Sharon Cray 5.3 .97 5 23
southnorth SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Particia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .7 4 20
northeast NE am Main JR. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
wangdongsheng ST Neu Soft 8.8 .77 6 5
2. sed '/north/p' datafile
默认情况下sed会打出全部的,如果在某一行匹配到模式north ,sed会多打一遍此行.
3. sed -n 'north/p' datafile
-n 与p命令配合使用,sed 取消了sed的缺省打印动作,如果不指定n这个选项,
sed就会从复打印north选项,如果指定了n就只打印模式north的那几行.
4. sed '3d' datafile
d命令就是删除第3行内容。
5.sed'3,$d' datafile
删除第3行到最后一行的内容。
6. sed '$d' datafile
删除最后一行.
7. sed '/north/d' datafile
删除包含所有行的north;其他的打印出来
8.sed 's/west/north/g'
把所有的west替换成north
9.sed -n 's/^west/north/p' datafile
搜索行首带west的行,并将替换为north,并打印出来
10.sed 's/[0-9][0-9]$/&.5/' datafile
与符号(&)在替换穿中时,代表查找串中匹配内容。这个例子中以两位数字结尾的行后面都被加上.5如果要在替换串中表示“与”号字面的含义,就要对起进行转义,记为:\&
11. sed -n 's/Hemenway/Jones/gp' datafile
文件中出现所有Hemenway都被替换为Jones,唯一发生变化的行被打印.选项-n与p的组合取消了缺省的输出,标志g含义在行内进行全局替换。
12. sed -n 's/\(Mar\)got/\lianne/p' datafile
扩在括号里的模式Mar作为标签1被保存与特殊寄存器中,替换串通、1引用它,Margot被替换为Marianne.
13. sed 's#3#88#g' datafile
紧跟在S命令的字符是查找和替换之间的分隔符。分隔符缺省的正斜杠,但可以改变(只在使用s命令时).无论什么字符,只要紧跟着s命令就成新的串分隔符,这个方法在查找包含正斜杠的模式时很管用,例如查找路径名和生日.
14. sed -n '/west/,/east/p' datafile
打印在west和east之间的所有行,如果west出现在east之后的某一行,则打印的范围从west所在行开始,到下一个出现east的行或文件末尾。
15. sed -n '5,/^northeast/p' datafile
打印前5行到第一个以northeast开头的行之间的所有行.
16 '/west/,/east/s/$/***WANGDONGSHENG***/' datafile
修改模式east和west之间的所有行,将各行的行尾($)替换为字符串***WANGDONGSHENG***换行符号被移动到这个新的字符串后面,箭头标出了范围.
17. sed -e '1,3d' -e 's/Hemenway/Jones' datafile
-e的作用是先删除1到3行,然后把Hemenway替换Jones,因为这是逐行编辑的(即两个命令都在模式空间上执行),所以编辑的顺序会影响结果.例如如果两条命令都是执行替换,则前一行替换会影响后一行.
18.sed -n '/north/w newfile' datafile
w命令是把指定写入文件。文件datafile中所有包含模式north的行都写到文件newfile中
19.sed '/^north /a\\---->the north sales district has moved<---' datafile
a为追加命令,字符串the north sales district has moved被加在以north开头,north
后跟一空格的各行之后,用于追加文本必须出现在追加命令下一行上.
20.sed '/eastern/i\\NEW REGLAND REGION\\---------------------------' datafile
i命令是插入命令。如果某一行匹配到模式eastern,i命令就在该行上放插入命令中反斜
杠后的文本,除了最后一行,用于插入文本中每一行都必须以反斜杠结尾
21.sed '/eastern/{ n; s/AM/Archie/; }' datafile
如果在某一行匹配到模式eastern,n命令就是指sed用下一个输入行(即包括AM Main Jr 的那行)
替换模式空间中的当前行,用Archie替换(s)其中的AM,然后打印
22. sed'1,3y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ' datafile
y命令把第一到第3行所有小写字母换成大写字母。正则表达式对y不起作用.
23 sed '5q' datafile
打印第5行之后,q命令让sed程序退出
24 'Lewis/{ s/Lewis/Joseph/;q; }' datafile
在某行匹配模式到Lewis时,先用Joseph替换(s)Lewis然后q命令退出
25 sed -e '/northeast/h' -e '$G' datafile
如果在某一行找到模式WE,h命令就将该行从模式缓冲区拷贝到一个暂存的缓冲区
保存在暂存缓冲区的行可以在以后被重新取出(使用命令G或g),这个例子中,当模式WE
被找到时将模式缓冲区的那份拷贝删除,
26.sed -e '/WE/{h; d; }' -e '/CT/{G; }' datafile
sed处理文件时,会把文件每一行都保存在一个临时的缓冲区中,这个缓冲区会被称为模式空间。sed处理每一行后,都会将其打印在屏幕上,除非该行被删除会被取消。之后模式空间清空,下一输入行等待处理。本例子中,被包含的模式northeast的行被找到之后,就被保存在模式空间里h命令把复制并保存到另一个缓冲区,这个特殊的缓冲区是暂存的缓冲区(holding buffer)在第二条sed命令中,sed读到最后一行($)时,G命令指示它从暂存缓冲区读出一行,将其放回模式缓冲区,追加在模式空间内当前行(本例中是最后一行)的后面
sed 's/^[]*//g' filename
sed 's/^ *//g' filename
sed 's/^[[:space:]]*//g' filename
删除以.结尾行 s/^.$//g
删除以一个以上空格,用一个空格代替 s/[][][]*/[]/g
删除空行 /^$/d
删除第一个字符 s/^.//g
删除所有空格并用Tab键代替 s/[]/[ ]//g
删除行首所有Tab键 s/^[ ]//g
删除所有Tab键 s/[ ]*//g
cat datafile
northwest NW Charles Main 3.0 .98 3 34
northern WE Sharon Cray 5.3 .97 5 23
southnorth SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Particia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .7 4 20
northeast NE am Main JR. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
wangdongsheng ST Neu Soft 8.8 .77 6 5
2. sed '/north/p' datafile
默认情况下sed会打出全部的,如果在某一行匹配到模式north ,sed会多打一遍此行.
3. sed -n 'north/p' datafile
-n 与p命令配合使用,sed 取消了sed的缺省打印动作,如果不指定n这个选项,
sed就会从复打印north选项,如果指定了n就只打印模式north的那几行.
4. sed '3d' datafile
d命令就是删除第3行内容。
5.sed'3,$d' datafile
删除第3行到最后一行的内容。
6. sed '$d' datafile
删除最后一行.
7. sed '/north/d' datafile
删除包含所有行的north;其他的打印出来
8.sed 's/west/north/g'
把所有的west替换成north
9.sed -n 's/^west/north/p' datafile
搜索行首带west的行,并将替换为north,并打印出来
10.sed 's/[0-9][0-9]$/&.5/' datafile
与符号(&)在替换穿中时,代表查找串中匹配内容。这个例子中以两位数字结尾的行后面都被加上.5如果要在替换串中表示“与”号字面的含义,就要对起进行转义,记为:\&
11. sed -n 's/Hemenway/Jones/gp' datafile
文件中出现所有Hemenway都被替换为Jones,唯一发生变化的行被打印.选项-n与p的组合取消了缺省的输出,标志g含义在行内进行全局替换。
12. sed -n 's/\(Mar\)got/\lianne/p' datafile
扩在括号里的模式Mar作为标签1被保存与特殊寄存器中,替换串通、1引用它,Margot被替换为Marianne.
13. sed 's#3#88#g' datafile
紧跟在S命令的字符是查找和替换之间的分隔符。分隔符缺省的正斜杠,但可以改变(只在使用s命令时).无论什么字符,只要紧跟着s命令就成新的串分隔符,这个方法在查找包含正斜杠的模式时很管用,例如查找路径名和生日.
14. sed -n '/west/,/east/p' datafile
打印在west和east之间的所有行,如果west出现在east之后的某一行,则打印的范围从west所在行开始,到下一个出现east的行或文件末尾。
15. sed -n '5,/^northeast/p' datafile
打印前5行到第一个以northeast开头的行之间的所有行.
16 '/west/,/east/s/$/***WANGDONGSHENG***/' datafile
修改模式east和west之间的所有行,将各行的行尾($)替换为字符串***WANGDONGSHENG***换行符号被移动到这个新的字符串后面,箭头标出了范围.
17. sed -e '1,3d' -e 's/Hemenway/Jones' datafile
-e的作用是先删除1到3行,然后把Hemenway替换Jones,因为这是逐行编辑的(即两个命令都在模式空间上执行),所以编辑的顺序会影响结果.例如如果两条命令都是执行替换,则前一行替换会影响后一行.
18.sed -n '/north/w newfile' datafile
w命令是把指定写入文件。文件datafile中所有包含模式north的行都写到文件newfile中
19.sed '/^north /a\\---->the north sales district has moved<---' datafile
a为追加命令,字符串the north sales district has moved被加在以north开头,north
后跟一空格的各行之后,用于追加文本必须出现在追加命令下一行上.
20.sed '/eastern/i\\NEW REGLAND REGION\\---------------------------' datafile
i命令是插入命令。如果某一行匹配到模式eastern,i命令就在该行上放插入命令中反斜
杠后的文本,除了最后一行,用于插入文本中每一行都必须以反斜杠结尾
21.sed '/eastern/{ n; s/AM/Archie/; }' datafile
如果在某一行匹配到模式eastern,n命令就是指sed用下一个输入行(即包括AM Main Jr 的那行)
替换模式空间中的当前行,用Archie替换(s)其中的AM,然后打印
22. sed'1,3y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ' datafile
y命令把第一到第3行所有小写字母换成大写字母。正则表达式对y不起作用.
23 sed '5q' datafile
打印第5行之后,q命令让sed程序退出
24 'Lewis/{ s/Lewis/Joseph/;q; }' datafile
在某行匹配模式到Lewis时,先用Joseph替换(s)Lewis然后q命令退出
25 sed -e '/northeast/h' -e '$G' datafile
如果在某一行找到模式WE,h命令就将该行从模式缓冲区拷贝到一个暂存的缓冲区
保存在暂存缓冲区的行可以在以后被重新取出(使用命令G或g),这个例子中,当模式WE
被找到时将模式缓冲区的那份拷贝删除,
26.sed -e '/WE/{h; d; }' -e '/CT/{G; }' datafile
sed处理文件时,会把文件每一行都保存在一个临时的缓冲区中,这个缓冲区会被称为模式空间。sed处理每一行后,都会将其打印在屏幕上,除非该行被删除会被取消。之后模式空间清空,下一输入行等待处理。本例子中,被包含的模式northeast的行被找到之后,就被保存在模式空间里h命令把复制并保存到另一个缓冲区,这个特殊的缓冲区是暂存的缓冲区(holding buffer)在第二条sed命令中,sed读到最后一行($)时,G命令指示它从暂存缓冲区读出一行,将其放回模式缓冲区,追加在模式空间内当前行(本例中是最后一行)的后面
sed 's/^[]*//g' filename
sed 's/^ *//g' filename
sed 's/^[[:space:]]*//g' filename
删除以.结尾行 s/^.$//g
删除以一个以上空格,用一个空格代替 s/[][][]*/[]/g
删除空行 /^$/d
删除第一个字符 s/^.//g
删除所有空格并用Tab键代替 s/[]/[ ]//g
删除行首所有Tab键 s/^[ ]//g
删除所有Tab键 s/[ ]*//g