shell 识别三种命令: 内建命令 shell函数 外部命令
外部命令是由shell 新的进程所执行的命令
a 建立一个新的进程
b 在path 里查找
c找到新进程取代执行中的shell
在shell的变量值可以是null
ex:fullname = “a b c” 包含空格时 需用引号
fullname = “$a $b $c” 多个变量连接也要引号
print 会自动包含\n printf 则需要执行添加
关于path
path=:/bin:/usr/bin 先查找当前
path=/bin:/usr/bin: 最后查找当前
path=/bin::/usr/bin 中间查找当前 (注意的是:冒号)
locale -a 列出所有系统说支持的locale
locale -ck 查询特定的locale变量
ex:locale -ck LC_TIME
在正则下
\ 关闭后续字符的特殊定义,但\(\) \{\}会打开其特殊定义
. 任何单个字符
* 0个或多个 在它之前的单个字符
单独出现时 在BRE中不具有任何意义(因为前面为空 就什么都没有)
^ 在BRE中 在表达式开头处具有意义
在ERE中 任何位置都有意义
$ 同上,只是他代表的是结尾处
[] 匹配方括号内任一字符
- 在这里的意思是连续 ex:1-9 1到9
^ 代表非
在方括号表达式中,所有的meta字符都会失去特殊含义
[]*\.-]这个例子比较特殊 对] 跟- 放进[]里的位置有些许讲究
\(['"]\).*\1 这个的意思是 ''或者“”,
不用担心单引号先找到或者是双引号先找到
注:BRE 基础正则表达式 ERE 扩展正则表达式
注:
[::] 字符集 ex: [:alpha:] 字母字符 [:alnum:] 数字字符
[:upper:] 大写 [:lower:] 小写 [:space:] 空格
[..] 多字符序列视为一个单位
[==]等价字符集 对于有音标的才需要
后向引用
\( \) 配一个\n
ex:\( \)\1 表示引用前面的一次,那就是() () 原来有一次,再应用一次
另外注意的是,n代表1-9 最多可以9次的应用,顺序是从左开始
-------
((read|write)[[:space:]]*)+
解释 : ( )+ 一次或多次括号里面的
( ) [[:space:]]* ()后接一个或多个空格
read|write 在ERE里面这个表示交替 不是read就是write
------
\< 匹配单词头
\> 匹配档次尾
\< \> 只匹配单词
-----------
head -n
awk 'FNR <= n ' (FNR是在当前输入文件的记录数)
sed -e nq
作用都是类似的 打印前N行
sed定界符可以变,不一定是/
sed 's:/a:/b:'
sed 's/a/&,abcd' &代表了前面的表达式
sed 's/ /av' 空格代表 使用上一次所使用的表达式
sed 的完整表达式是address +commend
所以sed 可以
sed '/a/s/#/$/' 指定一个地址,行
表示从含有a那行开始,再匹配#,然后将其转换为$
sed '/a/,/b/s/#/$/'
从含有a那行开始,到含有b的那行结束,所有行第一个#取代为$
-------
${varname:-word}
如果varname存在且不是null,则返回他的值,否则返回默认值
${count:-0} 如果count没定义,则值为0
${varname:=word}
如果varname存在且不是null,则返回他的值,则设置变量为默认值
${count:=0} 如果count未定义,则count设置为0
${varname:?message}
如果varname存在且不是null,则返回他的值,否则,显示message并退出当前命令
${count:?"undefined!"} 如果count未定义,就显示count:undefined并退出
${varname:+word}
如果varname存在且不是null,则返回word,否则返回null
${count:+1} 如果count已定义,则返回1
------
# 从前面开始匹配的,并删除匹配最短
## 从前面开始匹配的,并删除匹配最长
$ 从后面开始匹配,并删除匹配最短
$$ 从后面开始匹配,并删除匹配最长
------
$# 进程参数个数
$@ 当前命令行的参数,置于双引号内,展开为个别参数
$* 当前命令行的参数,置于双引号内,展开为单独参数
个别参数即单个字符串 "$1 $2" 单独参数即单独字符串 "$1" "$2"
$? 前一命令的退出状态
$$ 当前进程pid
$0 程序的名称
$! 最近一个后台命令的进程编号
IFS shell默认的分割字段的,默认值是空格 tab 换行
PPID 父进程编号
ps4
------
test -u suid
-g sgid
-z string为null
-n string是非null
= sting1与string2相同
-eq 整数相等
------
[-abc-] 匹配字符-abc之一
[^ab^c] 匹配不是a或b或^或c的任意字符
字符]和[放在[]中,只有紧跟在[后面的]和紧贴于]前面的[是普通字符
^ - [ ]这几个字符在[]中的意义和其位置有关,原理就不多说了,就写这几个例子。
^\(.\) 行中第一个字符存到1号寄存器中
^\(.\)\1 行首两个字符,且他们相同
^\(.\).*\1$ 行首尾两个字符相同
[0-1][0-9][-/][0-3][0-9][-/][0-9]\{2\}
这个表达式能够用来表示时间格式MM-DD-YY或MM/DD/YY,方括号[]中的-放在第一个位置,确保它在[]中不被解释为范围,而是普通字符-
^.*$和.*都匹配任意行(包括空行)
shell的*相当于re的.*
shell的?相当于re的.
shell的*和?也不是任何地方有意义的,一般用于路径中扩展文件名(至于有没有其他地方用还不知道)
sed 命令的基本格式(单引号里面的格式)
sed '地址 动作' 地址和动作之间不需要空格(这里方便看)
地址有2种形式:
1、行号,以数字表示;特殊的,行号中的$表示尾行(其他地方表示行尾)
2、模式,以//包围正则构成。
地址最多可以指定2个,且指定2个时需要用逗号,隔开表示范围;行号和模式可以混用。如:
sed '/a/,$s/#/$/' file
sed '1,/a/s/#/$/' file
当某个地址后有超过一个动作,需要使用{}和;
sed '/a/,${s/#/$/;s/#/$/2}' file 2表示替换第二个(最好实验一下,你会有新发现)
-----
test 的内容再整合一下
test -u suid
-g sgid
-z string为null
-n string是非null
= sting1与string2相同 !=不等
-eq 整数相等 -ne不等 -gt大于 -ge大于等于 -lt小于 -le小于等于 都是整数比较
-e file 存在
-d file 目录
-f file 普通文件
-r file 可读
-w file 可写
-x file 可执行
-s file 长度不为0
-L file 符号链接
-a 并且
-o 或者
! 非
-----
单引号' '屏蔽所有字符的特殊意义(包括回车)
双引号" "屏蔽大多数字符的特殊意义,除了美元$ 反斜杠\ 反引号`
反斜杠' '屏蔽所有单个字符的特殊意义,相当于 '单个字符'(但是有一些小意外)
以上普通的例子就不举了,说一下上面提到的“意外”:
当反斜杠用于一行的最后一个字符时,shell把行尾的反斜杠作为续行,它去掉跟在后面的换行字符,
也不把换行符当作参数分隔符(就像该字符从来没有键入过一样)。这种结构在分几行键入命令时经常使用。
\n \r \b \t 等等有自身的特殊意义,不在反斜杠屏蔽的范围里面,但是放在单引号内的话照样全部屏蔽。
另外再提一下,单、双引号都能屏蔽换行、空格和Tab的参数分隔(IFS)意义,利用这一点可以在脚本中用引号
输入大段文字而不用担心换行的问题,管道符|也有这个作用。
-----
再说一下if [ ]
if这个东西几乎在所有变成语言里都有,大多数语言中if的格式都是if (condition)....有的后面有then,有的没有。
其他语言中的if( )和shell中的if [ ]很像,只是括号的样子不一样而已。然而他们是有本质区别的!
if ( )中的( )是个固定格式(大部分语言中是这样),不能变的;而if [ ]中的[ ]是shell的内部命令,并不是固定的
格式。shell中的if的标准格式是
if command
then
commands
fi
if根据它后面command的返回状态来判断执行then后面的commands还是不执行:返回0就执行,非0就不执行。
[ ]是shell内置的判断命令,和命令test等效。所以当你看到if后面不是[ ]时,请不要惊讶。
-----
sed的N命令:追加下一行
多行Next(N)命令通过读取当前行的下一行,并把两行拼成一行来进行接下来的处理。
$ cat file
line 1
line 2
line 3
line 4
file文件中的每一行后面都有一个隐藏的换行符”\n”,sed不对每行末尾的”\n”进行处理。
$ sed N file
line 1
line 2
line 3
line 4
经过N处理过的输出和原文件没有区别,但是本质是不一样的。这里sed其实认为自己打印的是2行,第一行为”line 1\nline 2”,而第2行为”line 3\nline 4”,注意这里的2行末尾依然隐藏换行符”\n”,sed依然不处理行尾的”\n”,但是处理行内的”\n”。因为这里默认的动作是打印,所以处理行内的”\n”我们也看不出来。
值得注意的是,处理line 1时,line 2被读入并追加到line 1后面,所以line 1处理完后不再读入line 2(前面已经读过了)而直接读入line 3进行下一个N命令(即读入line 4并追加到line 3后面)。
上面2段如果不理解的话,看下面这个命令:
$ sed ‘N;s/\n/ /g’ file
line 1 line 2
line 3 lin3 4
这个命令在原来的基础上把行内的”\n”替换成空格了(尽管用了全局替换标志g,sed依然不处理行尾换行符!),看明白N的作用了吗,单独的N可以创建2行模式空间。
阅读(792) | 评论(0) | 转发(0) |