问题
这里,我们给出了一个模式规则来产生[.d]文件:
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< >; $@.
; \
sed 's,$∗
\.o[ :]*,\1.o $@ : ,g' < $@.
>; $@; \
rm -f $@.
这个规则的意思是,所有的[.d]文件依赖于[.c]文件,“rm -f $@”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“$<”,也就是[.c]文件生成依赖文件,“$@”表示模式“%.d”文件,如果有一个C文件是name.c,那么“%”就是“name”,“
”意为一个随机编号,第二行生成的文件有可能是“name.d.12345”,第三行使用sed命令做了一个替换,关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。
上面代码的解释1:
%.d: %.c
$(CC) -M $(CPPFLAGS) $< > $@.
; \
sed 's,$∗
\.o[ :]*,\1.o $@ : ,g' < $@.
> $@; \
rm -f $@.
p-162:sed替换命令的格式是‘s///g’如果没有g,则sed的替换操作只对文本中的第一次出现的匹配模式进行替换。关于‘s///’命令的另一个注意点是‘/’分隔符有许多替换选项。如果正在执行字符串替换,并且规则表达式或替换字符串中有许多斜杠,则可以通过在’s’之后指定一个不同的字符来更改分隔符。例如,下列将把所有出现的/usr/local替换成/usr:
sed –e ‘s:/usr/local:/usr:g’ mylist.txt
在该例中,使用冒号作为分隔符。如果需要在规则表达式中使用分隔符,可以在它前面加入反斜杠。关于
是保留的模式空间,参见p-70,$* 是makefile中匹配的“茎”,
表示当前进程的进程号,命令行中还运用了输入输出重定向。
上面代码的解释2:
这是sed命令的用法了。Stream Editor
简单来讲就是替换。这里采用逗号作为基本语法的分隔。一般的形式是sed 's/pattern/new/g'
$∗
\.o[ :]*替换为\1.o $@ :
后面的g表示全局替换,就是不止替换一次。
同时又是用在makefile当中,所以要牵扯到$*,$@之类的自动变量。
$*,表示的是target的除去了suffix后的filename,也就是%.d: %.c当中的%部分。
$@,表示的是target,也就是%.d
sed操作的文件是来自上面命令的生成的临时文件$@.
最后再把sed的输出定向到零时文件$@.
后面的\都是为了和下面的命令连成一行,然后都用用;分隔,所以都是放在一个subshell当中执行。
没有猜错的话,这应该是Manage project with GNU make 3rd Edition当中的例子。
sed命令例子
在makefile里经常看到sed指令,经常看到替换功能,今天写了个makefile来学习下sed的替换功能,makefile如下:
- test = abcdefghisdabcjsdlfkj
-
-
- test2 = $(test) | sed -e 's/abc/123/g'
- debug:
- @echo $(test)
- @echo $(test2)
然后输入make debug,看到如下输入:
- abcdefghisdabcjsdlfkj
- 123defghisd123jsdlfkj
abc被替换成了123,如果不加字母g,结果就变成了只有第一个abc被替换,另外可以在复杂的makefile里使用echo指令来显示一些变量,有助学习makefile
================================================================
================================================================
================================================================
1. 在Makefile中想使用shell脚本,需要添加"@"符号,例如:
@if [ -d xxx ]; then \ //-d 判断是否存在,在shell中,用[]号代替括号
rm -rf xxx; \
fi;
@cp -fv xxx xxxx //-f 删除已经存在的目标文件而不提示 -v cp命令将告诉用户正在做什么
例: cp -fv temp temp2
显示: 'temp' -> 'temp2'
//查找所有的KO文件,并拷贝
@find sor_dir -name "*.ko" -exec sudo cp -vf '{}' des_dir ';'
@echo "OK."
2. sed 是linux下文本处理工具
格式:sed 's/要替换的字符串/新的字符串/g' (要替换的字符串可以用正则表达式)
//例如将某一个文件xxxx中相关字符串替换
@cat xxxx | sed "s/0000/9999/g" | sed "s/\/\/#define 7777/#define 8888/g" > xxxx2
=================================================================================
=================================================================================
=================================================================================
Linux sed命令
Linux 命令大全
Linux sed命令是利用script来处理文本文件。
sed可依照script的指令,来处理、编辑文本文件。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
语法
sed [-hnV][-e<script>][-f<script文件>][文本文件]
参数说明:
- -e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。
- -f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
- -h或--help 显示帮助。
- -n或--quiet或--silent 仅显示script处理后的结果。
- -V或--version 显示版本信息。
动作说明:
- a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
- c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
- d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
- i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
- p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
- s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!
实例
在testfile文件的第四行后添加一行,并将结果输出到标准输出,在命令行提示符下输入如下命令:
sed -e 4a\newLine testfile
首先查看testfile中的内容如下:
$ cat testfile #查看testfile 中的内容
HELLO LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test
使用sed命令后,输出结果如下:
$ sed -e 4a\newline testfile #使用sed 在第四行后添加新字符串
HELLO LINUX! #testfile文件原有的内容
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test
newline
以行为单位的新增/删除
将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除!
[root@www ~]# nl /etc/passwd | sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....
sed 的动作为 '2,5d' ,那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行罗~ 另外,注意一下,原本应该是要下达 sed -e 才对,没有 -e 也行啦!同时也要注意的是, sed 后面接的动作,请务必以 '' 两个单引号括住喔!
只要删除第 2 行
nl /etc/passwd | sed '2d'
要删除第 3 到最后一行
nl /etc/passwd | sed '3,$d'
在第二行后(亦即是加在第三行)加上『drink tea?』字样!
[root@www ~]# nl /etc/passwd | sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(后面省略).....
那如果是要在第二行前
nl /etc/passwd | sed '2i drink tea'
如果是要增加两行以上,在第二行后面加入两行字,例如『Drink tea or .....』与『drink beer?』
[root@www ~]# nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....(后面省略).....
每一行之间都必须要以反斜杠『 \ 』来进行新行的添加喔!所以,上面的例子中,我们可以发现在第一行的最后面就有 \ 存在。
以行为单位的替换与显示
将第2-5行的内容取代成为『No 2-5 number』呢?
[root@www ~]# nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync
.....(后面省略).....
透过这个方法我们就能够将数据整行取代了!
仅列出 /etc/passwd 文件内的第 5-7 行
[root@www ~]# nl /etc/passwd | sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
</p><p>
可以透过这个 sed 的以行为单位的显示功能, 就能够将某一个文件内的某些行号选择出来显示。
</p>
<h3>数据的搜寻并显示</h3>
<p>搜索 /etc/passwd有root关键字的行</p>
<pre>
nl /etc/passwd | sed '/root/p'
1 root:x:0:0:root:/root:/bin/bash
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3 bin:x:2:2:bin:/bin:/bin/sh
4 sys:x:3:3:sys:/dev:/bin/sh
5 sync:x:4:65534:sync:/bin:/bin/sync
....下面忽略
如果root找到,除了输出所有行,还会输出匹配行。
使用-n的时候将只打印包含模板的行。
nl /etc/passwd | sed -n '/root/p'
1 root:x:0:0:root:/root:/bin/bash
数据的搜寻并删除
删除/etc/passwd所有包含root的行,其他行输出
nl /etc/passwd | sed '/root/d'
2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3 bin:x:2:2:bin:/bin:/bin/sh
....下面忽略
#第一行的匹配root已经删除了
数据的搜寻并执行命令
搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行:
nl /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}'
1 root:x:0:0:root:/root:/bin/blueshell
最后的q是退出。
数据的搜寻并替换
除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并取代。基本上 sed 的搜寻与替代的与 vi 相当的类似!他有点像这样:
sed 's/要被取代的字串/新的字串/g'
先观察原始信息,利用 /sbin/ifconfig 查询 IP
[root@www ~]# /sbin/ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:90:CC:A6:34:84
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::290:ccff:fea6:3484/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
.....(以下省略).....
本机的ip是192.168.1.100。
将 IP 前面的部分予以删除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g'
192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
接下来则是删除后续的部分,亦即: 192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
将 IP 后面的部分予以删除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g'
192.168.1.100
多点编辑
一条sed命令,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell
nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
-e表示多点编辑,第一个编辑命令删除/etc/passwd第三行到末尾的数据,第二条命令搜索bash替换为blueshell。
直接修改文件内容(危险动作)
sed 可以直接修改文件的内容,不必使用管道命令或数据流重导向! 不过,由於这个动作会直接修改到原始的文件,所以请你千万不要随便拿系统配置来测试! 我们还是使用下载的 regular_express.txt 文件来测试看看吧!
利用 sed 将 regular_express.txt 内每一行结尾若为 . 则换成 !
[root@www ~]# sed -i 's/\.$/\!/g' regular_express.txt
利用 sed 直接在 regular_express.txt 最后一行加入『# This is a test』
[root@www ~]# sed -i '$a # This is a test' regular_express.txt
由於 $ 代表的是最后一行,而 a 的动作是新增,因此该文件最后新增『# This is a test』!
sed 的『 -i 』选项可以直接修改文件内容,这功能非常有帮助!举例来说,如果你有一个 100 万行的文件,你要在第 100 行加某些文字,此时使用 vim 可能会疯掉!因为文件太大了!那怎办?就利用 sed 啊!透过 sed 直接修改/取代的功能,你甚至不需要使用 vim 去修订!
Linux 命令大全
===========================================================================================
===========================================================================================
============================================================================================
================================================================================================
sed:Stream Editor文本流编辑,sed是一个“非交互式的”面向字符流的编辑器。能同时处理多个文件多行的内容,可以不对原文件改动,把整个文件输入到屏幕,可以把只匹配到模式的内容输入到屏幕上。还可以对原文件改动,但是不会再屏幕上返回结果。
sed命令的语法格式:
sed的命令格式: sed [option] 'sed command'filename
sed的脚本格式:sed [option] -f 'sed script'filename
sed命令的选项(option):
-n :只打印模式匹配的行
-e :直接在命令行模式上进行sed动作编辑,此为默认选项
-f :将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作
-r :支持扩展表达式
-i :直接修改文件内容
sed在文件中查询文本的方式:
1)使用行号,可以是一个简单数字,或是一个行号范围
x | x为行号 |
x,y | 表示行号从x到y |
/pattern | 查询包含模式的行 |
/pattern /pattern | 查询包含两个模式的行 |
pattern/,x | 在给定行号上查询包含模式的行 |
x,/pattern/ | 通过行号和模式查询匹配的行 |
x,y! | 查询不包含指定行号x和y的行 |



2)使用正则表达式、扩展正则表达式(必须结合-r选项)
^ | 锚点行首的符合条件的内容,用法格式"^pattern" |
$ | 锚点行首的符合条件的内容,用法格式"pattern$" |
^$ | 空白行 |
. | 匹配任意单个字符 |
* | 匹配紧挨在前面的字符任意次(0,1,多次) |
.* | 匹配任意长度的任意字符 |
\? | 匹配紧挨在前面的字符0次或1次 |
\{m,n\} | 匹配其前面的字符至少m次,至多n次 |
\{m,\} | 匹配其前面的字符至少m次 |
\{m\} | 精确匹配前面的m次\{0,n\}:0到n次 |
\< | 锚点词首----相当于 \b,用法格式:\<pattern |
\> | 锚点词尾,用法格式:\>pattern |
\<pattern\> | 单词锚点 |
| | 分组,用法格式:pattern,引用\1,\2 |
[] | 匹配指定范围内的任意单个字符 |
[^] | 匹配指定范围外的任意单个字符 |
[:digit:] | 所有数字, 相当于0-9, [0-9]---> [[:digit:]] |
[:lower:] | 所有的小写字母 |
[:upper:] | 所有的大写字母 |
[:alpha:] | 所有的字母 |
[:alnum:] | 相当于0-9a-zA-Z |
[:space:] | 空白字符 |
[:punct:] | 所有标点符号 |
- #######sed的匹配模式支持正则表达式#####################
- sed'5 q'/etc/passwd#打印前5行
- sed-n '/r*t/p'/etc/passwd#打印匹配r有0个或者多个,后接一个t字符的行
- sed-n '/.r.*/p'/etc/passwd#打印匹配有r的行并且r后面跟任意字符
- sed-n '/o*/p'/etc/passwd#打印o字符重复任意次
- sed-n '/o\{1,\}/p'/etc/passwd#打印o字重复出现一次以上
- sed-n '/o\{1,3\}/p'/etc/passwd#打印o字重复出现一次到三次之间以上
sed的编辑命令(sed command):
p | 打印匹配行(和-n选项一起合用) |
= | 显示文件行号 |
a\ | 在定位行号后附加新文本信息 |
i\ | 在定位行号后插入新文本信息 |
d | 删除定位行 |
c\ | 用新文本替换定位文本 |
w filename | 写文本到一个文件,类似输出重定向 > |
r filename | 从另一个文件中读文本,类似输入重定向 < |
s | 使用替换模式替换相应模式 |
q | 第一个模式匹配完成后退出或立即退出 |
l | 显示与八进制ACSII代码等价的控制符 |
{} | 在定位行执行的命令组,用分号隔开 |
n | 从另一个文件中读文本下一行,并从下一条命令而不是第一条命令开始对其的处理 |
N | 在数据流中添加下一行以创建用于处理的多行组 |
g | 将模式2粘贴到/pattern n/ |
y | 传送字符,替换单个字符 |
对文件的操作无非就是”增删改查“,怎样用sed命令实现对文件的”增删改查“,玩转sed是写自动化脚本必须的基础之一。
sed命令打印文件信息(查询):
- ####用sed打印文件的信息的例子的命令######
- sed -n '/^#/!p' /etc/vsftpd/vsftpd.conf
- sed -n '/^#/!{/^$/!p}' /etc/vsftpd/vsftpd.conf
- sed -e '/^#/d' -e '/^$/d' /etc/vsftpd/vsftpd.conf
- sed -n '1,/adm/p' /etc/passwd
- sed -n '/adm/,6p' /etc/passwd
- sed -n '/adm/,4p' /etc/passwd
- sed -n '/adm/,2p' /etc/passwd
- ###以下图片是对这些sed命令例子的解释和显示结果




sed命令实现对文件内容的添加:(对源文件添加的话就用-i参数):
- ####sed命令可以实现的添加######
- #1)匹配行的行首添加,添加在同行
- #2)匹配行的行中的某个字符后添加
- #3)匹配行的行尾添加字符
- #4)匹配行的行前面行添加
- #5)匹配行的行后面行添加
- #6)文件的行首添加一行
- [root@jie1 ~]# sed -i '1 i\sed command start' myfile
- #7)文件的行尾追加一行
- [root@jie1 ~]# sed -i '$a \sed command end' myfile









sed命令实现对文件内容的删除:(对源文件直接删除用-i参数):
sed的删除操作是针对文件的行,如果想删除行中的某个字符,那就用替换(别急,替换稍后就讲,而且替换是sed最常用的)




重点:sed命令实现对文件内容的替换(替换是在shell自动化脚本中用到最多的操作)
- #================源文件里面的内容===============================
- [root@jie1 ~]# cat test
- anonymous_enable=YES
- write_enable=YES
- local_umask=022
- xferlog_enable=YES
- connect_from_port_20=YES
- root:x:0:0:root:/root:/bin/bash
- bin:x:1:1:bin:/bin:/sbin/nologin
- daemon:x:2:2:daemon:/sbin:/sbin/nologin
- adm:x:3:4:adm:/var/adm:/sbin/nologin
- lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
- DEVICE="eth0"
- BOOTPROTO="static"
- HWADDR="00:0C:29:90:79:78"
- ONBOOT="yes"
- IPADDR=172.16.22.1
- NETMASK=255.255.0.0
- #======================================================================
- [root@jie1 ~]# sed -i '/DEVICE/c\Ethernet' test
- #匹配DEVICE的行,替换成Ethernet这行
- [root@jie1 ~]# sed -i 's/static/dhcp/' test
- #把static替换成dhcp(/,@,#都是前面所说的地址定界符)
- [root@jie1 ~]# sed -i '/IPADDR/s@22\.1@10.12@' test
- #匹配IPADDR的行,把22.1替换成10.12由于.号有特殊意义所有需要转义
- [root@jie1 ~]# sed -i '/connect/s#YES#NO#' test
- #匹配connect的行,把YES替换成NO
- [root@jie1 ~]# sed -i 's/bin/tom/2g' test
- #把所有匹配到bin的行中第二次及第二次之后出现bin替换成tom
- [root@jie1 ~]# sed -i 's/daemon/jerry/2p' test
- #把所有匹配到bin的行中第二次出现的daemon替换成jerry,并在生产与匹配行同样的行
- [root@jie1 ~]# sed -i 's/adm/boss/2' test
- #把所有匹配到adm的行中仅仅只是第二次出现的adm替换成boss
- [root@jie1 ~]# sed -i '/root/{s/bash/nologin/;s/0/1/g}' test
- #匹配root的行,把bash替换成nologin,且把0替换成1
- [root@jie1 ~]# sed -i 's/root/(&)/g' test
- #把root用括号括起来,&表示引用前面匹配的字符
- [root@jie1 ~]# sed -i 's/BOOTPROTO/#BOOTPROTO/' test
- #匹配BOOTPROTO替换成#BOOTPROTO,在配置文件中一般用于注释某行
- [root@jie1 ~]# sed -i 's/ONBOOT/#&/' test
- #匹配ONBOOT的行的前面添加#号,在配置文件中也表示注释某行
- [root@jie1 ~]# sed -i '/ONBOOT/s/#//' test
- #匹配ONBOOT的行,把#替换成空,即去掉#号,也一般用作去掉#注释
- #================执行以上sed命令之后文件显示的内容====================
- [root@jie1 ~]# cat test
- anonymous_enable=YES
- write_enable=YES
- local_umask=022
- xferlog_enable=YES
- connect_from_port_20=NO
- (root):x:1:1:(root):/(root):/bin/nologin
- bin:x:1:1:tom:/tom:/stom/nologin
- daemon:x:2:2:jerry:/sbin:/stom/nologin
- daemon:x:2:2:jerry:/sbin:/stom/nologin
- adm:x:3:4:boss:/var/adm:/sbin/nologin
- lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
- Ethernet
- #BOOTPROTO="dhcp"
- HWADDR="00:0C:29:90:79:78"
- ONBOOT="yes"
- IPADDR=172.16.10.12
- NETMASK=255.255.0.0
sed引用变量:(在自动化shell脚本 中也经常会使用到变量)
第一种当sed命令里面没有默认的变量时可以把单引号改成双引号;
第二种当sed命令里面有默认的变量时,那自己定义的变量需要加单引号,且sed里面的语句必须用单引
- [root@jie1 ~]# cat >> myfile << EOF
- > hello world
- > i am jie
- > how are you
- > EOF #先生成一个文件
- [root@jie1 ~]# cat myfile
- hello world
- i am jie
- how are you
- [root@jie1 ~]# name=li
- #定义一个变量,且给变量赋值
- [root@jie1 ~]# sed -i "s/jie/$name/" myfile
- #把匹配jie的字符替换成变量的值
- [root@jie1 ~]# cat myfile
- hello world
- i am li
- how are you
- [root@jie1 ~]# sed -i "$a $name" myfile
- #当sed命令也有默认变量时,在去引用自己定义的变量会出现语法错误
- sed: -e expression #1, char 3: extra characters after command
- [root@jie1 ~]# sed -i '$a '$name'' myfile
- #在引用自定义的变量时,sed语句必须用单引引住,然后把自定义的变量也用单引号引住
- [root@jie1 ~]# cat myfile
- hello world
- i am li
- how are you
- li
- [root@jie1 ~]#
sed的其它高级使用:
1)把正在用sed操作的文件的内容写到例外一个文件中
- [root@jie1 ~]# cat test #sed操作的文件中的内容
- Ethernet
- #BOOTPROTO="dhcp"
- HWADDR="00:0C:29:90:79:78"
- ONBOOT="yes"
- IPADDR=172.16.10.12
- NETMASK=255.255.0.0
- [root@jie1 ~]# sed -i 's/IPADDR/ip/w ip.txt' test
- #把sed操作的文件内容保存到另外一个文件中,w表示保存,ip.txt文件名
- [root@jie1 ~]# cat ip.txt #查看新文件的内容
- ip=172.16.10.12
- [root@jie1 ~]#
2)读取一个文件到正在用sed操作的文件中
- [root@jie1 ~]# cat myfile #文件内容
- hello world
- i am li
- how are you
- li
- [root@jie1 ~]# cat test #将用sed操作的文件的内容
- Ethernet
- #BOOTPROTO="dhcp"
- HWADDR="00:0C:29:90:79:78"
- ONBOOT="yes"
- IPADDR=172.16.10.12
- NETMASK=255.255.0.0
- [root@jie1 ~]# sed -i '/Ethernet/r myfile' test
- #在匹配Ethernet的行,读进来另一个文件的内容,读进来的文件的内容会插入到匹配Ethernet的行后
- [root@jie1 ~]# cat test #再次查看用sed命令操作的行
- Ethernet
- hello world
- i am li
- how are you
- li
- #BOOTPROTO="dhcp"
- HWADDR="00:0C:29:90:79:78"
- ONBOOT="yes"
- IPADDR=172.16.10.12
- NETMASK=255.255.0.0
- [root@jie1 ~]#
sed的经典例子:
- ##1)、处理以下文件内容,将域名取出并进行计数排序,如处理:
- http:
- http:
- http:
- http:
- http:
- http:
- 得到如下结果:
- 域名的出现的次数 域名
- 3 www.baidu.com
- 2 post.baidu.com
- 1 mp3.baidu.com
- [root@localhost shell]# cat file | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn
- 3 www.baidu.com
- 2 post.baidu.com
- 1 mp3.baidu.com
- [root@codfei4 shell]# awk -F/ '{print $3}' file |sort -r|uniq -c|awk '{print $1"\t",$2}'
- 3 www.baidu.com
- 2 post.baidu.com
- 1 mp3.baidu.com
- ##2)、用grep结合sed取出网卡的ip地址
- [root@jie1 ~]# ifconfig | grep -B1 "inet addr" |grep -v "\-\-" |sed -n -e 'N;s/eth[0−9].*\n.*addr:[0−9]{1,3}\.[0−9]{1,3}\.[0−9]{1,3}\.[0−9]{1,3}.*/\1 \2/p'
学会sed的使用是写自动化shell脚本的基础,sed也是一个非常有用且重要的命令,是文本处理工具之一,以上是我自己学习总结的sed命令简单的用法,sed还有更高级的用法,也还在学习中。
=================================================================================
=================================================================================
==================================================================================
sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
sed的选项、命令、替换标记
命令格式
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
选项
-e<script>或--expression=<script>:以选项中的指定的script来处理输入的文本文件;
-f<script文件>或--file=<script文件>:以选项中指定的script文件来处理输入的文本文件;
-h或--help:显示帮助;
-n或--quiet或——silent:仅显示script处理后的结果;
-V或--version:显示版本信息。
参数
文件:指定待处理的文本文件列表。
sed命令
a\ 在当前行下面插入文本。
i\ 在当前行上面插入文本。
c\ 把选定的行改为新的文本。
d 删除,删除选择的行。
D 删除模板块的第一行。
s 替换指定字符
h 拷贝模板块的内容到内存中的缓冲区。
H 追加模板块的内容到内存中的缓冲区。
g 获得内存缓冲区的内容,并替代当前模板块中的文本。
G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。
l 列表不能打印字符的清单。
n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
N 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
p 打印模板块的行。
P(大写) 打印模板块的第一行。
q 退出Sed。
b lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
r file 从file中读行。
t label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
w file 写并追加模板块到file末尾。
W file 写并追加模板块的第一行到file末尾。
! 表示后面的命令对所有没有被选定的行发生作用。
= 打印当前行号码。
# 把注释扩展到下一个换行符以前。
sed替换标记
g 表示行内全面替换。
p 表示打印行。
w 表示把行写入一个文件。
x 表示互换模板块中的文本和缓冲区中的文本。
y 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
\1 子串匹配标记
& 已匹配字符串标记
sed元字符集
^ 匹配行开始,如:/^sed/匹配所有以sed开头的行。
$ 匹配行结束,如:/sed$/匹配所有以sed结尾的行。
. 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d。
* 匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
[] 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed。
[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\) 匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\< 匹配单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\> 匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\} 重复字符x,m次,如:/0\{5\}/匹配包含5个0的行。
x\{m,\} 重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行。
x\{m,n\} 重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行。
sed用法实例
替换操作:s命令
替换文本中的字符串:
sed 's/book/books/' file
-n选项和p命令一起使用表示只打印那些发生替换的行:
sed -n 's/test/TEST/p' file
直接编辑文件选项-i,会匹配file文件中每一行的第一个book替换为books:
sed -i 's/book/books/g' file
全面替换标记g
使用后缀 /g 标记会替换每一行中的所有匹配:
sed 's/book/books/g' file
当需要从第N处匹配开始替换时,可以使用 /Ng:
echo sksksksksksk | sed 's/sk/SK/2g'
skSKSKSKSKSK
echo sksksksksksk | sed 's/sk/SK/3g'
skskSKSKSKSK
echo sksksksksksk | sed 's/sk/SK/4g'
skskskSKSKSK
定界符
以上命令中字符 / 在sed中作为定界符使用,也可以使用任意的定界符:
sed 's:test:TEXT:g'
sed 's|test|TEXT|g'
定界符出现在样式内部时,需要进行转义:
sed 's/\/bin/\/usr\/local\/bin/g'
删除操作:d命令
删除空白行:
sed '/^$/d' file
删除文件的第2行:
sed '2d' file
删除文件的第2行到末尾所有行:
sed '2,$d' file
删除文件最后一行:
sed '$d' file
删除文件中所有开头是test的行:
sed '/^test/'d file
已匹配字符串标记&
正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词:
echo this is a test line | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]
所有以192.168.0.1开头的行都会被替换成它自已加localhost:
sed 's/^192.168.0.1/&localhost/' file
192.168.0.1localhost
子串匹配标记\1
匹配给定样式的其中一部分:
echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
this is 7 in a number
命令中 digit 7,被替换成了 7。样式匹配到的子串是 7,\(..\) 用于匹配子串,对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2,例如:
echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
BBB aaa
love被标记为1,所有loveable会被替换成lovers,并打印出来:
sed -n 's/\(love\)able/\1rs/p' file
组合多个表达式
sed '表达式' | sed '表达式'
等价于:
sed '表达式; 表达式'
引用
sed表达式可以使用单引号来引用,但是如果表达式内部包含变量字符串,就需要使用双引号。
test=hello
echo hello WORLD | sed "s/$test/HELLO"
HELLO WORLD
选定行的范围:,(逗号)
所有在模板test和check所确定的范围内的行都被打印:
sed -n '/test/,/check/p' file
打印从第5行开始到第一个包含以test开始的行之间的所有行:
sed -n '5,/^test/p' file
对于模板test和west之间的行,每行的末尾用字符串aaa bbb替换:
sed '/test/,/west/s/$/aaa bbb/' file
多点编辑:e命令
-e选项允许在同一行里执行多条命令:
sed -e '1,5d' -e 's/test/check/' file
上面sed表达式的第一条命令删除1至5行,第二条命令用check替换test。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。
和 -e 等价的命令是 --expression:
sed --expression='s/test/check/' --expression='/love/d' file
从文件读入:r命令
file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面:
sed '/test/r file' filename
写入文件:w命令
在example中所有包含test的行都被写入file里:
sed -n '/test/w file' example
追加(行下):a\命令
将 this is a test line 追加到 以test 开头的行后面:
sed '/^test/a\this is a test line' file
在 test.conf 文件第2行之后插入 this is a test line:
sed -i '2a\this is a test line' test.conf
插入(行上):i\命令
将 this is a test line 追加到以test开头的行前面:
sed '/^test/i\this is a test line' file
在test.conf文件第5行之前插入this is a test line:
sed -i '5i\this is a test line' test.conf
下一个:n命令
如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续:
sed '/test/{ n; s/aa/bb/; }' file
变形:y命令
把1~10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令:
sed '1,10y/abcde/ABCDE/' file
退出:q命令
打印完第10行后,退出sed
sed '10q' file
保持和获取:h命令和G命令
在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将 打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。
sed -e '/test/h' -e '$G' file
在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。
保持和互换:h命令和x命令
互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换:
sed -e '/test/h' -e '/check/x' file
脚本scriptfile
sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。
sed [options] -f scriptfile file(s)
打印奇数行或偶数行
方法1:
sed -n 'p;n' test.txt #奇数行
sed -n 'n;p' test.txt #偶数行
方法2:
sed -n '1~2p' test.txt #奇数行
sed -n '2~2p' test.txt #偶数行
打印匹配字符串的下一行
grep -A 1 SCC URFILE
sed -n '/SCC/{n;p}' URFILE
awk '/SCC/{getline; print}' URFILE
====================================================================================================================================================================================================================================================================================================================================================================================================================
#
注释符号(Hashmark[Comments])
1.在shell文件的行首,作为shebang标记,#!/bin/bash;
2. 其他地方作为注释使用,在一行中,#后面的内容并不会被执行,除非;
3. 但是用单/双引号包围时,#作为#号字符本身,不具有注释作用。
;
作为多语句的分隔符(Command separator [semicolon])。
多个语句要放在同一行的时候,可以使用分号分隔。注意,有时候分号需要转义。
;;
连续分号(Terminator [double semicolon])。
在使用case选项的时候,作为每个选项的终结符。在Bash version 4+ 的时候,还可以使用[;;&], [;&]
.
点号(dot command [period])。
1. 相当于bash内建命令source,如:
#!/bin/bash. data-file#包含data-file;
2. 作为文件名的一部分,在文件名的开头,表示该文件为隐藏文件,ls一般不显示出来(ls -a 可以显示);
3. 作为目录名,一个点代表当前目录,两个点号代表上层目录(当前目录的父目录)。注意,两个以上的点不出现,除非你用引号(单/双)包围作为点号字符本身;
4. 正则表达式中,点号表示任意一个字符。
"
双引号(partial quoting [double quote])。
部分引用。双引号包围的内容可以允许变量扩展,也允许转义字符的存在。如果字符串内出现双引号本身,需要转义,因此不一定双引号是成对的。
'
单引号(full quoting [single quote])。
单引号括住的内容,被视为单一字符串,引号内的禁止变量扩展,所有字符均作为字符本身处理(除单引号本身之外),单引号必须成对出现。
,
逗号(comma operator [comma])。
1. 用在连接一连串的数学表达式中,这串数学表达式均被求值,但只有最后一个求值结果被返回。如:
#!/bin/bashlet t1=((a=5+1, b=7+2))echo t1=$t1, a=$a, b=$b## 这个$t1=$b;
2. 用于参数替代中,表示首字母小写,如果是两个逗号,则表示全部小写,注意,这个特性在bash version 4的时候被添加的。例子:
a="ATest"echo ${a,}echo ${a,,}## 前面输出aTest,后面输出的是atest。
\
反斜线,反斜杆(escape [backslash])。
1. 放在特殊符号之前,转义特殊符号的作用,仅表示特殊符号本身,这在字符串中常用;
2. 放在一行指令的最末端,表示紧接着的回车无效(其实也就是转义了Enter),后继新行的输入仍然作为当前指令的一部分。
/
斜线,斜杆(Filename path separator [forward slash])。
1.作为路径的分隔符,路径中仅有一个斜杆表示根目录,以斜杆开头的路径表示从根目录开始的路径;
2.在作为运算符的时候,表示除法符号。如:a=4/2
`
反引号,后引号(Command substitution[backquotes])。
命令替换。这个引号包围的为命令,可以执行包围的命令,并将执行的结果赋值给变量。如:a=`dirname '/tmp/x.log'` 。后面dirname返回的结果会赋值给a,注意,此处Mitchell特地使用了反引号和单引号,注意区别。
:
冒号(null command [colon])。
空命令,这个命令什么都不做,但是有返回值,返回值为0(即:true)。这个命令的作用非常奇妙。
1. 可做while死循环的条件;
2. 在if分支中作为占位符(即某一分支什么都不做的时候);
3. 放在必须要有两元操作的地方作为分隔符,如:: ${username=`whoami`}
4. 在参数替换中为字符串变量赋值,在重定向操作(>)中,把一个文件长度截断为0(:>>这样用的时候,目标存在则什么都不做),这个只能在普通文件中使用,不能在管道,符号链接和其他特殊文件中使用;
5. 甚至你可以用来注释(#后的内容不会被检查,但:后的内容会被检查,如果有语句如果出现语法错误,则会报错);
6. 你也可以作为域分隔符,比如环境变量$PATH中,或者passwd中,都有冒号的作为域分隔符的存在;
7. 你也可以将冒号作为函数名,不过这个会将冒号的本来意义转变(如果你不小心作为函数名,你可以使用unset -f : 来取消function的定义)。
!
感叹号(reverse (or negate) [bang],[exclamation mark])。
取反一个测试结果或退出状态。
1. 表示反逻辑,比如后面的!=,这个是表示不等于;
2. 表示取反,如:ls a[!0-9] #表示a后面不是紧接一个数字的文件;
3. 在不同的环境里面,感叹号也可以出现在间接变量引用里面;
4. 在命令行中,可以用于历史命令机制的调用,你可以试试!$,!#,或者!-3看看,不过要注意,这点特性不能在脚本文件里面使用(被禁用)。
*
星号(wildcard/arithmetic operator[asterisk])。
1. 作为匹配文件名扩展的一个通配符,能自动匹配给定目录下的每一个文件;
2. 正则表达式中可以作为字符限定符,表示其前面的匹配规则匹配任意次;
3. 算术运算中表示乘法。
**
双星号(double asterisk)。算术运算中表示求幂运算。
?
问号(test operator/wildcard[Question mark])。
1. 表示条件测试;
2. 在双括号内表示C风格的三元操作符((condition?true-result:false-result));
3. 参数替换表达式中用来测试一个变量是否设置了值;
4. 作为通配符,用于匹配文件名扩展特性中,用于匹配单个字符;
5. 正则表达式中,表示匹配其前面规则0次或者1次。
$
美元符号(Variable substitution[Dollar sign])。
1. 作为变量的前导符,用作变量替换,即引用一个变量的内容,比如:echo $PATH;
2. 在正则表达式中被定义为行末(End of line)。
${}
参数替换(Variable substitution)。
用于在字符串中表示变量。
$‘...’
引用内容展开,执行单引号内的转义内容(单引号原本是原样引用的),这种方式会将引号内的一个或者多个[\]转义后的八进制,十六进制值展开到ASCII或Unicode字符。
$*
$@
位置参数(Positional Parameters)。
这个在使用脚本文件的时候,在传递参数的时候会用到。两者都能返回调用脚本文件的所有参数,但$*是将所有参数作为一个整体返回(字符串),而$@是将每个参数作为单元返回一个参数列表。注意,在使用的时候需要用双引号将$*,$@括住。这两个变量受到$IFS的影响,如果在实际应用中,要考虑其中的一些细节。
$#
表示传递给脚本的参数数量。
$?
此变量值在使用的时候,返回的是最后一个命令、函数、或脚本的退出状态码值,如果没有错误则是0,如果为非0,则表示在此之前的最后一次执行有错误。
$$
进程ID变量,这个变量保存了运行当前脚本的进程ID值。
()
圆括号(parentheses)。
1, 命令组(Command group)。由一组圆括号括起来的命令是命令组,命令组中的命令实在子shell(subshell)中执行。因为是在子shell内运行,因此在括号外面是没有办法获取括号内变量的值,但反过来,命令组内是可以获取到外面的值,这点有点像局部变量和全局变量的关系,在实作中,如果碰到要cd到子目录操作,并在操作完成后要返回到当前目录的时候,可以考虑使用subshell来处理;
2. 用于数组的初始化。
{x,y,z,...}
花括号扩展(Brace Expansion)。
在命令中可以用这种扩展来扩展参数列表,命令将会依照列表中的括号分隔开的模式进行匹配扩展。注意的一点是,这花括号扩展中不能有空格存在,如果确实有必要空格,则必须被转义或者使用引号来引用。例子:echo {a,b,c}-{\ d," e",' f'}
{a..z}
在Bash version 3时添加了这种花括号扩展的扩展,可以使用{A..Z}表示A-Z的所有字符列表,这种方式的扩展Mitchell测试了一下,好像仅适用于A-Z,a-z,还有数字{最小..最大}的这种方式扩展。
{}
代码块(curly brackets)。
这个是匿名函数,但是又与函数不同,在代码块里面的变量在代码块后面仍能访问。注意:花括号内侧需要有空格与语句分隔。另外,在xargs -i中的话,还可以作为文本的占位符,用以标记输出文本的位置。
{} \;
这个{}是表示路径名,这个并不是shell内建的,现在接触到的情况看,好像只用在find命令里。注意后面的分号,这个是结束find命令中-exec选项的命令序列,在实际使用的时候,要转义一下以免被shell理解错误。
[]
中括号(brackets)。
1. 测试的表示,Shell会测试在[]内的表达式,需要注意的是,[]是Shell内建的测试的一部分,而非使用外部命令/usr/bin/test的链接;
2. 在数组的上下文中,表示数组元素,方括号内填上数组元素的位置就能获得对应位置的内容,如:
Array[1]=xxxecho ${Array[1]};
3. 表示字符集的范围,在正表达式中,方括号表示该位置可以匹配的字符集范围。
[[]]
双中括号(double brackets)。
这个结构也是测试,测试[[]]之中的表达式(Shell的关键字)。这个比单中括号更能防止脚本里面的逻辑错误,比如:&&,||,<,>操作符能在一个[[]]里面测试通过,但是在[]却不能通过。[[]]里面没有文件名扩展(filename expansion)或是词分隔符(Word splitting),但是可以用参数扩展(Parameter expansion)和命令替换(command substitution)。不用文件名通配符和像空白这样的分隔符。注意,这里面如果出现了八进制,十六进制等,shell会自动执行转换比较。
$[...]
词表达表示整数扩展(integer expansion)。
在方括号里面执行整数表达式。例:
a=3b=7echo $[$a+$b]echo $[$a*$b]##返回是10和21
(())
双括号(double parentheses)。
表示整数扩展(integer expansion)。功能和上面的$[]差不多,但是需要注意的是,$[]是会返回里面表达式的值的,而(())只是执行,并不会返回值。两者执行后如果变量值发生变化,都会影响到后继代码的运行。可对变量赋值,可以对变量进行一目操作符操作,也可以是二目,三目操作符。
>
&<
>&
>>
<
<>
重定向(redirection)。
scriptname >filename 重定向scriptname的输出到文件filename中去,如果文件存在则覆盖;
command &>filename 重定向command的标准输出(stdout)和标准错误(stderr)到文件filename中;
command >&2 把command的标准输出(stdout)重定向到标准错误(stderr)中;
scriptname >>filename 把scriptname的输出(同>)追加到文件filenmae中,如果文件不存在则创建。
[i]<>filename 打开filename这个文件用来读或者写,并且给文件指定i为它的文件描述符(file descriptor),文件不存在就会创建。
(command)>
<(command)
这是进程替换(Process Substitution)。
使用的时候注意,括号和<,>之间是不能有空格的,否则报错。其作用有点类似通道,但和管道在用法上又有些不同,管道是作为子进程的方式来运行的,这个命令会在/dev/fd/下面产生类似/dev/fd/63,/dev/fd/62这类临时文件,用来传递数据。
Mitchell个人猜测之所以用这种方法来传递,是因为前后两个不属于同一个进程,因此需要用共享文件的方式来传递资料(这么说其实管道也应该有同样的文件?)。网上有人说这个只是共享文件而已,但是经过测试,发现虽然有/dev/fd/63这样的文件产生,但是这个文件其实是指向pipe:[43434]这样的通道的链接。
<<
双小于号(here-document[double less then marks])。
这个也被称为Here-document,用来将后继的内容重定向到左侧命令的stdin中。<<可以节省格式化时间,别且使命令执行的处理更容易。在实作的时候只需要输入<<和终止标志符,而后(一般是回车后)你就可以输入任何内容,只要在最后的新行中输入终止标志符,即可完成数据的导入。使用here-document的时候,你可以保留空格,换行等。如果要让shell脚本更整洁一点,可以在<<和终止符之间放上一个连字符(-)。
<<<
三个小于号(here-strings)。Here-字串和Here-document类似,here-strings语法:command [args] <<<["]$word["];$word会展开并作为command的stdin。
<
>
小于,大于号(ASCII Comparison)。
ASCII比较,进行的是变量的ASCII比较,字串?数字?呃...这个...不就是ASCII比较么?
\<...\>
词界符(word boundary)。
这个是用在正则表达式中的一个特殊分隔符,用来标记单词的分界。比如:the会匹配there,another,them等等,如果仅仅要匹配the,就可以使用这个词界符,\<the\>就只能匹配the了。
|
管道(pipe)。管道是Linux,Unix都有的概念,是非常基础,也是非常重要的一个概念。它的作用是将管道前(左边)的命令产生的输出(stdout)作为管道后(右边)的命令的输入(stdin)。如:ls | wc l,使用管道就可以将命令连接在一起。注意:管道是每一个进程的标准输出都会作为下一个命令的标准输入,期间的标准输出不能跨越管道作为后继命令的标准输入,如: cat filename | ls -al | sort 。想想这个的输出? 同时,管道是以子进程来运行的,所以管道并不能引起变量改变。
>|
强制重定向(force redirection)。
这会强制重写已经存在的文件。
&
与号(Run job in background[ampersand])。
如果命令后面跟上一个&符号,这个命令将会在后台运行。有的时候,脚本中在一条在后台运行的命令可能会引起脚本挂起,等待输入,出现这种情况可以在原有的脚本后面使用wait命令来修复。
&&
||
逻辑操作符(logical operator)。
在测试结构中,可以用这两个操作符来进行连接两个逻辑值。||是当测试条件有一个为真时返回0(真),全假为假;&&是当测试条件两个都为真时返回真(0),有假为假。
-
减号,连字符(Hyphen/minus/dash)。
1. 作为选项,前缀[option, prefix]使用。用于命令或者过滤器的选项标志;操作符的前缀。如:
## COMMAND -[选项列表]ls -alsort -dfu $fileset -- $variable
if [ $file -ot $file2 ]then echo "$file is older than $file2."fi
2. 用于stdin或者stdout的重定向的源或目的[dash].在tar没有bunzip2的程序补丁时,我们可以这样: bunzip2 linux-2.6.13.tar.bz2 | tar xvf - 。将前面解压的数据作为tar的标准输入(这里使用一个-表示)
注意:在实作的时候,如果文件名是以[-]开头的,那么在加上这个作为定向操作符的时候,可能会出错,此时应该为文件加上合适的前缀路径,以避免这种情况发生,同样的,在echo变量的时候,如果变量是以[-]开始,那么可能也会产生意想不到的结果,为了保险起见,可以使用双引号引用标量:
var="-n"echo $var## 试试看有什么输出?
还有,这种表示方法不是Bash内建的,要达到此点的这种效果,需要看你使用的软件是否支持这种操作;
3. 表示先前的工作目录(previous working directory),因此,如果你cd到其他目录下要放回前一个路径的时候,可以使用cd -来达到目的,其实,这里的[-]使用的是环境变量的$OLDPWD,注意:这里的[-]和前一点是不同的;
4. 减号或者负号,用在算术操作中。
=
等号(Equals)。
1. 赋值操作,给变量赋值,么有空格在等号两侧;
2. 在比较测试中作为比较符出现,这里要注意,如果在中括号中作为比较出现,需要有空格符在等号左右两侧。
+
加号(Plus)。
1. 算术操作符,表示加法;
2. 在正则表达式中,表示的是其前的这个匹配规则匹配最少一次;
3.在命令或过滤器中作为选项标记,在某些命令或者内置命令中使用+来启用某些选项,使用-来禁止;
4. 在参数替换(parameter substitution)中,+前缀表示替代值(当变量为空的时候,使用+后面的值)
%
百分号(modulo[percent sign])。
1.在算术运算中,这个是求模操作符,即两个数进行除法运算后的余数;
2. 在参数替换(parameter substitution)中,可以作为模式匹配。例子:
p=b*9var="abcd12345abc479"echo ${var%p}, ${var%%p}##从右边开始查找(想想从左是那个符号?)##任何在b和9之间的内容(含)##第一个是找到最短的符合匹配项##后一个是找最大符合的匹配项(贪婪匹配?)
~
波浪号(Home directory[tilde])。
这个和内部变量$HOME是一样的。默认表示当前用户的家目录(主目录),这个和~/效果一致,如果波浪号后面跟用户名,表示是该用户的家目录。
~+
当前的工作目录(current working directory)。
这个和内置变量$PWD一样。
~-
前一个工作目录(previous working directory)。
这个和内部变量$OLDPWD一致,之前的[-]也一样。
=~
Bash 版本3中有介绍,这个是正则表达式匹配。可用在[[]]测试中,比如:
var="this is a test message."[[ "$var" =~ tf*message ]] && echo "Sir. Found that." || echo "Sorry Sir. No match be found."##你可以修改中间的正则表达式匹配项,正则表达式可以但不一定需要使用双引号括起来。
^
脱字符(caret)。
1. 在正则表达式中,作为一行的行首(beginning-of-line)位置标志符;
2. 在参数替换(Parameter substitution)中,这个用法有两种,一个脱字符(${var^}),或两个(${var^^}),分别表示第一个字母大写,全部大写的意思(Bash version >=4)。
空白
空白符(Whitespace)。
空白符不仅仅是指空格(spaces),还包括制表符(tabs),空行(blank lines),或者这几种的组合。可用做函数的分隔符,分隔命令或变量,空行不会影响脚本的行为,因此可以用它来规划脚本代码,以增加可读性,在内置的特殊变量$IFS可以用来针对某些命令进行输入的参数进行分割,其默认就是空白符。在字符串或变量中如果有空白符,可以使用引号来规避可能的错误。
人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。