ChinaUnix首页 > 精华文章 > Shell > 正文

[原创] 大家跟我学SHELL (与本教程有关的疑问可在此提问)


http://www.chinaunix.net 作者:levopat  发表于:2007-01-09 15:15:46
发表评论】 【查看原文】 【Shell讨论区】【关闭

一、选择一个好SHELL

Unix 中常见的 shell 主要分为两大门派:

sh:
burne shell (sh)

burne again shell (bash)


        csh:
c shell (csh)

tc shell (tcsh)
korn shell (ksh)


本人的教学环境是 FreeBSD6.1 + sh ,你也可以使用bash来学习,bash兼容sh。我尽量将所有的SHELL语句也在Redhat上面验证一下。

FreeBSD上bash的安装方法有二:
1、pkg_add -r bash

2、cd /usr/ports/shell/bash2 && make install clean


Linux 上默认的SHELL已经是bash了。

查看自己机器上支持 Shell 种类的方法:
# cat /etc/shells


/bin/sh

/bin/csh
/bin/tcsh
/usr/local/bin/bash


设置自己的SHELL为sh

# chsh
# vipw


使用chsh命令会打开一个编辑器(类似vi),需要修改其中的Shell: /bin/csh一项为Shell: /bin/sh
使用vipw命令会打开一个编辑器(类似vi),需要修改指定用户所在行的最后一项为/bin/sh

如果你是在FreeBSD上安装了 bash ,一般修改为 /usr/local/bin/bash


二、SHELL基础(UNIX中的常用命令)

[color=Red]列出目录中的内容[/color]
ls

[color=Red]FreeBSD需要使用使用-G参数,才能按文件类型显示为约定的颜色[/color]
ls -G

[color=Red]使用长格式,更出目录中的内容[/color]
ls -l

[color=Red]显示一个文本文件的内容[/color]
cat <文件名>
cat -n /etc/passwd  (显示文件,并加行号)
less <文件名>
more <文件名>

[color=Red]复制文件[/color]cp <源文件名> <目标文件名>

[color=Red]文件更名或移动文件至其他目录[/color]

mv <文件名1> <文件名2>
mv <目录1><文件名> <目录2><文件名>

[color=Red]显示当前工作的目录[/color]
pwd 

[color=Red]建立目录(-p 建立多级目录)[/color]
mkdir <目录名>
mkdir -p <目录1>/<目录2>

[color=Red]删除文件(或目录)[/color]
rm <文件名>
rm -rf <目录>

[color=Red]显示时间和日期[/color]
date

[color=Red]显示N天前的时间和日期[/color]

date -v -2d

[color=Red]其他格式请自己试一下,或查看手册  man date[/color]
date +%F
date "+DATE: %Y-%m-%d%nTIME: %H:%M:%S"

[color=Red]显示字符串[/color]
echo "hello c shell"
printf "hello c shell\n"

[color=Red]显示带颜色的字符串[/color]
echo -e "\e[31mRed String\e[0m"
printf  "\e[31mRed String\e[0m\n"

具体的颜色代码,请参考: http://www.51sincere.com/2006-11/20061123123521.htm

[ 本帖最后由 levopat 于 2007-1-4 08:14 编辑 ]



 awk就是awp加ak 回复于:2006-12-05 16:39:05

支持一下!偶没基础,是得听听 :mrgreen:


 sealearner 回复于:2006-12-05 18:28:10

yes,这些都会,但是没有找过man,很多命令的option都是不懂,en太差,唉。。。。。。。。。


 levopat 回复于:2006-12-05 20:49:46

三、字符统计( wc )
[color=Red]wc 可以按单词(-w)、行数(-l)、字符(-c)进行统计[/color]

wc -w 文件名
wc -w < 文件名


 levopat 回复于:2006-12-05 20:59:08

四、字符匹配(*、?)

ls
ls *
ls ?
星号(*)匹配0个或0个以上的字符
问号(?)匹配1个字符

ls [a-z]*
配置以小写字母开头的文件名

ls [0-9]*
配置以数字开头的文件名

ls *[!a-z]
匹配不以小写字母结尾的文件名

echo *
相当于显示当前所有匹配的文件名
其实SHELL是经过以上转换步骤的
1、* 被当前目录下所有的文件名替换
2、显示(echo)出这些文件名


 levopat 回复于:2006-12-05 21:08:53

五、查看谁在线(who)
w
who
users
列出目前在线人名单

whoami
who am i
查看自己的登录名

id
id -p
查看自己的登录ID及登录名

uptime
显示系统运行情况
时间 系统运行时间 登录用户数 系统负载

last
显示用户最后一次的登录终端等信息

lastlogin
显示用户最后登录时间

[ 本帖最后由 levopat 于 2006-12-8 10:37 编辑 ]


 levopat 回复于:2006-12-05 21:30:55

六、管道(>、>>、|、<)

who > users (将who的输出保存到文件users)
who >> users (将show的输出追加到文件users后面)

true > access.log (清空文件)
echo '' > access.log (清空文件)

wc -l < users (统计users文件的行数)
cat users | wc -l (同上)
ps  (显示进程列表)
ps | sort (对进程列表进行排序)

[ 本帖最后由 levopat 于 2006-12-7 15:02 编辑 ]


 bob.tu 回复于:2006-12-05 21:33:33

好啊!支持!跟你一起学。。。基础


 levopat 回复于:2006-12-05 21:33:46

七、将命令发送到后台运行 (&)
sort date > out &

nohup sort date > out & (退出当前登录,命令仍可在后台运行)


 levopat 回复于:2006-12-05 21:38:26

例:
echo -e "\e[44;37;5m Hello \e[0m Color"

以上命令设置背景成为蓝色,前景白色,闪烁光标,输出字符“Hello ”,
然后重新设置屏幕到缺省设置,输出字符“Color”。“e”是命令echo的
一个可选项,它用于激活特殊字符的解析器。“\e”引导非常规字符序
列。“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 设置缺省黑色背景

其他有趣的代码还有:

\e[2J 清除屏幕
\e[0q 关闭所有的键盘指示灯
\e[1q 设置“滚动锁定”指示灯 (Scroll Lock)
\e[2q 设置“数值锁定”指示灯 (Num Lock)
\e[3q 设置“大写锁定”指示灯 (Caps Lock)
\e[15:40H 把关闭移动到第15行,40列
\007 发蜂鸣生beep


 levopat 回复于:2006-12-06 10:14:03

已经讲过的命令,大家有什么不明白的可以提出来,一起讨论。互动学习效果更好。


 levopat 回复于:2006-12-06 10:28:48

八、给变量赋值

a=123
b="123 ABC"  (带空格的变量需要使用双引号(或单引号))
c="1234               abcd"  (此处含有多个空格)

echo $a
echo $b
echo $c
echo "$c"  (此处显示不会把多个空格变成一个空格)


let a=10  (赋值并显示变量值到终端)

read b  (从键盘读取值,并赋给变量b)
10
echo $b


 levopat 回复于:2006-12-06 10:40:16

九、变量的算术运算 

在sh(Bash) Shell中,只能进行两个整数间的运算,其结果仍为整数;

[color=Red]let命令,语法为: [/color]
let expr
例:
let 1 + 2
a=2
b=10
let $a + $b
let c=$a+$b


[color=Red]expr命令,例:[/color]
expr 1 + 2


[color=Red]$(()) 命令[/color]
d=$(( 2 + 3 ))
echo  $d


常见的算术运算符号,列举如下:
+,-,*,/,% 加,减,乘,除,取模




如果不是整数怎么办呢? 可以试试 bc 命令

[test@test]$ echo "9/2" | bc

4


[test@test]$ echo "9.5/2" | bc

4



[test@test]$ echo "9/2" | bc -l
4.50000000000000000000



[test@test]$ echo "9.5/2" | bc -l

4.75000000000000000000


以上几个例子,感谢网友"cnbsd5"的帮助.

[ 本帖最后由 levopat 于 2006-12-10 20:44 编辑 ]


 vepeta 回复于:2006-12-06 10:47:09

完成后编辑一下,放在一起吧。这样看了不累。呵呵


 andyrui 回复于:2006-12-06 10:56:00

谢谢啊!看了一边,影响加深了!


 levopat 回复于:2006-12-06 10:56:25

引用:原帖由 vepeta 于 2006-12-6 10:47 发表
完成后编辑一下,放在一起吧。这样看了不累。呵呵 




请多提宝贵意见


 levopat 回复于:2006-12-06 22:10:22

引用:原帖由 andyrui 于 2006-12-6 10:56 发表
谢谢啊!看了一边,影响加深了! 




有什么不太明白的地方,提出来大家一起讨论.


 levopat 回复于:2006-12-07 15:44:09

九、命令的返回值(SHELL的状态返回值)

当运行一个命令后,SHELL通常会返回一个状态码,该值一般为0或者一个正值
0表示正常运行,即成功。正值一般是运行出错,不同的值是在SHELL内部或内核里面定义的。

例:
ls /
echo $? (显示上一个SHELL的状态返回值)

a=3 (赋值)
test  a = 4 (测试a是否等于4)
echo $? (显示上面测试的结果,0为真(true),正值为假(false))


 L0ading 回复于:2006-12-07 18:53:14

不能开个语音聊天室聊吗


 Arthur_ 回复于:2006-12-07 19:43:39

ls *會羅列出很多文件包括子目錄中的文件
如果我只向羅列出當前目錄的文件應該如何做喔


 levopat 回复于:2006-12-08 08:49:29

引用:原帖由 Arthur_ 于 2006-12-7 19:43 发表
ls *會羅列出很多文件包括子目錄中的文件
如果我只向羅列出當前目錄的文件應該如何做喔 




ls 就可以了,如果需要显示详细的目录列表,使用ls -l

如果想带颜色显示,使用 ls -G 或 ls -lG



 siehon 回复于:2006-12-08 09:44:26

xuexi


 levopat 回复于:2006-12-08 09:48:45

十、简单介绍几个常用命令

[color=Red]1、paste[/color]

今天看到一个贴子:
如何将两行内容拼接成一行?

http://bbs.chinaunix.net/viewthread.php?tid=839952

使用paste命令可以去除文本中的换行符。示例:
paste <文件名>

如果想把两(一个)个文件按行并在一起,可以使用
paste <文件1> <文件2>


cat 1 
aa
bb
cc

cat 1 2
11
22
33

paste 1 2
aa      11
bb      22
cc      33

paste -s 1
aa      bb      cc

paste -d ' ' -s 1  (以空格为分格符, 合并文件中的行)
aa bb cc

paste -d '\0' -s 1 (不要分格符, 合并文件中的行)
aabbcc



[color=Red]2. 字符转换 (tr)[/color]

上例也可以使用 tr 来达到去除文件中的换行符,示例如下:

cat 1 | tr  "\012"  '\0' (把文件中的换行符转换成空NULL)

cat 1 | tr  "\012"  ','  (把文件中的换行符转换成逗号,)
cat 1 | tr  "\012"  ' '  (把文件中的换行符转换成空格)
cat 1 | tr -d "\012" (删除文件中的换行符)


[color=Green]注:换行符\n的八进制码就是012
回车符\r的八进制码就是015
[/color]


[ 本帖最后由 levopat 于 2006-12-8 15:16 编辑 ]


 honbj 回复于:2006-12-08 10:38:33

形式不错 不过有点乱 建议更系统些 多点例子


 levopat 回复于:2006-12-08 10:41:31

引用:原帖由 honbj 于 2006-12-8 10:38 发表
形式不错 不过有点乱 建议更系统些 多点例子 




多谢您的建议。如果你能加入进来,大家一起多举些例子就好了。
我目前只是利用业余时间把自己过去常用到的一些流水式的讲出来,
尽量能做到易学,易懂,易用。

例子部分,多是自己编的、或查看man中、或是从论坛中的问题中抽取的。
所以这个教程的贡献者就太多了。现在看贴的各位都是其他一位贡献者。

[ 本帖最后由 levopat 于 2006-12-8 10:45 编辑 ]


 liqxy 回复于:2006-12-08 11:12:29

好贴,顶!


 happy2008163 回复于:2006-12-08 13:51:47

好贴, 先谢谢了。         在跟你学呢, 看来还是买一本书好。没事,我又不下。 看下明白了,到用的时候有不知道了。     容易忘,    最好买一本书 , 要么就详细的记下来。


 levopat 回复于:2006-12-08 15:10:27

[color=Red]3、取字符串中的某一段(cut、awk)[/color]

例:
cut -d : -f 1,7 /etc/passwd  (取passwd 文件中的第1,7两列,以冒号:为分隔符)

$ cut -d : -f 1,7 /etc/passwd

# $FreeBSD
#
root:/bin/csh
toor:
daemon:/usr/sbin/nologin
operator:/usr/sbin/nologin
bin:/usr/sbin/nologin
tty:/usr/sbin/nologin
...


who | cut -c 1-16 (输出当前系统的登录用户名,按字符取1-16位)

$ who | cut -c 1-16

patli
levopat
root


cut -d : -f 1-3 /etc/passwd  (取passwd 文件中的第1-3列,以冒号:为分隔符)

$ cut -d : -f 1-3 /etc/passwd

# $FreeBSD: src/etc/master.passwd,v 1.40 2005/06/06 20:19
#
root:*:0
toor:*:0
daemon:*:1
operator:*:2
bin:*:3
tty:*:4


下面介绍awk 实现与上面相似的功能:
awk -F: '{print $1}' /etc/passwd
awk -F: '{print $1,$7}' /etc/passwd
awk -F: '{print $1":"$7}' /etc/passwd
awk -F: '{print $1"|"$7}' /etc/passwd
awk -F: '{print $1,$NF}' /etc/passwd  ($NF 为最后一列的值)
以上几个命令,请大家自选测试,理解输出的结果值。

[ 本帖最后由 levopat 于 2006-12-8 15:34 编辑 ]


 yy_bb_ll 回复于:2006-12-08 15:21:12

谢谢 楼主, 要是能把每个例子的运行结果都写出来就更好了


 levopat 回复于:2006-12-08 15:36:22

引用:原帖由 yy_bb_ll 于 2006-12-8 15:21 发表
谢谢 楼主, 要是能把每个例子的运行结果都写出来就更好了 




多谢指教,每个例子尽量列出结果。

我列出的结果是在FreeBSD6.1下面的sh环境下输出的,
大家也可以在自己的系统上运行,看看是否有与我的不一致的地方。


 levopat 回复于:2006-12-08 15:44:36

4、在文本文件中查找某个字符串(grep)

语法:
[color=Red]grep [选项] 模式 [文件名...][/color]

示例:
$ grep root /etc/passwd  (在passwd 中查找并返回带root的行)

root:*:0:0:Charlie &:/root:/bin/csh

toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin


grep -n root /etc/passwd  (在passwd 中查找并返回带root的行,并显示行号)

3:root:*:0:0:Charlie &:/root:/bin/csh

4:toor:*:0:0:Bourne-again Superuser:/root:
5:daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin


$ grep -l root /etc/*    在/etc目录中查找并返回带root的文件名)
/etc/passwd




grep -v root /etc/passwd  (在passwd 中查找并返回[color=Red]不[/color]带root的行)
# $FreeBSD: src/etc/master.passwd,v 1.40 2005/06/06 20:19:56 brooks Exp $

#
operator:*:2:5:System &:/:/usr/sbin/nologin
bin:*:3:7:Binaries Commands and Source:/:/usr/sbin/nologin
tty:*:4:65533:Tty Sandbox:/:/usr/sbin/nologin
kmem:*:5:65533:KMem Sandbox:/:/usr/sbin/nologin
games:*:7:13:Games pseudo-user:/usr/games:/usr/sbin/nologin
...



$ grep -R ifconfig /etc/*   (-R 表示也在子目录中查找)
/etc/devd.conf: action "ifconfig $device-name inet 1.2.3.4 netmask 0xffff0000";

grep: /etc/nsmb.conf: Permission denied
/etc/rc.conf:ifconfig_em0="inet 61.12.166.19  netmask 255.255.255.240"



[color=Red]补充: grep  的一些常用选项的含义[/color]
-c  只是输出一些匹配行的计数

-i  不区别大小写
-l 输出包含匹配的字符文件名
-n 显示匹配的行号
-v 显示不包含匹配的文本所有行
-s 不显示不存在或无匹配文本的错误信息



以下使用 awk 实现类似上面的功能

$awk '/root/' /etc/passwd

root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin


$ awk '/root/{print NR ":" $0}' /etc/passwd

3:root:*:0:0:Charlie &:/root:/bin/csh
4:toor:*:0:0:Bourne-again Superuser:/root:
5:daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin
26:wwwroot:*:3000:3000:User &:/www/vhost/wwwroot:/usr/sbin/nologin


以下使用 sed 实现类似上面的功能
$sed -n '/root/p' /etc/passwd


root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin


[ 本帖最后由 levopat 于 2006-12-19 09:34 编辑 ]


 jingzhi 回复于:2006-12-08 15:55:25

如果我想把屏幕背景色设置为白色,前景色设为黑色.一直有效改怎么设呢?


 levopat 回复于:2006-12-08 16:01:56

引用:原帖由 jingzhi 于 2006-12-8 15:55 发表
如果我想把屏幕背景色设置为白色,前景色设为黑色.一直有效改怎么设呢? 





我使用 putty.exe ,在配置里面可以更改
Configuration->Colours


如果你是FreeBSD,并且不想编内核的话,可以使用一个很简单的操作:
echo -e "\e[30;47m"

也可以把他放到你的 ~/.bash_profile 里面,每次登录会自动运行。

[ 本帖最后由 levopat 于 2006-12-8 16:04 编辑 ]


 cnbsd5 回复于:2006-12-09 06:29:37

看楼主挺辛苦的,我也补充一句:


九、变量的算术运算

在sh(Bash) Shell中,只能进行两个整数间的运算,其结果仍为整数;


以上""里内容是楼主说的,建议楼主修改下这条:

[test@test]$ echo "9/2" | bc
4
[test@test]$ echo "9.5/2" | bc
4
[test@test]$ echo "9/2" | bc -l
4.50000000000000000000
[test@test]$ echo "9.5/2" | bc -l
4.75000000000000000000

[ 本帖最后由 cnbsd5 于 2006-12-9 06:31 编辑 ]


 levopat 回复于:2006-12-10 20:45:44

引用:原帖由 cnbsd5 于 2006-12-9 06:29 发表
看楼主挺辛苦的,我也补充一句:


九、变量的算术运算

在sh(Bash) Shell中,只能进行两个整数间的运算,其结果仍为整数;


以上""里内容是楼主说的,建议楼主修改下这条:

[test@test] ... 





非常感谢您的提示,我已经修改了"变量的算术运算".以后还请您多多指教.


 levopat 回复于:2006-12-18 10:56:40

十一、更改文件权限(chmod)

语法: chmod [-cfvR] mode file...

Unix 的文件存取权限分3级: 文件拥有者、群组、其他。

mode : 权限设定字串,格式如下 : 

[ugoa...][+-=][rwx]...][,...],


其中

u 表示该文件的拥有者。

g 表示与该文件的拥有者属于同一个群体(group)者。

o 表示其他以外的人。

a 表示这三者皆是。

+ 表示增加权限、- 表示取消权限、= 表示唯一设定权限。

r 表示可读取,w 表示可写入,x 表示可执行

-c : 若该文件权限确实已经更改,才显示其更改动作

-f : 若该文件权限无法被更改也不要显示错误讯息

-v : 显示权限变更的详细资料

-R : 对目前目录下的所有文件与子目录进行相同的权限变更(即以递回的方式逐个变更)

举例 :

1、将文件 file1.txt 设为所有人皆可读取:

chmod   ugo+r file1.txt


2、将文件 file1.txt 设为所有人皆可读取:

chmod   a+r     file1.txt


3、 将文件 file1.txt 与 file2.txt 设为该文件拥有者,与其所属同一个群体者可写入,但其他人则不可写:

chmod   ug+w,o-w   file1.* 


4、将 file4.txt 设定为只有该文件拥有者可以执行:

chmod   u+x     file4.txt 


5、将目前目录下的所有文件与子目录皆设为任何人可读取:

chmod   -R a+r *


6、此外chmod也可以用数字来表示权限如 chmod   777  file

语法为:chmod --- file3

其中---各为一个数字,分别表示User、Group、及Other的权限。

r=4,w=2,x=1

若要rwx属性则4+2+1=7;

若要rw-属性则4+2=6;

若要r-x属性则4+1=5。

 

chmod a=rwx file 和 chmod 777 file 同。

chmod ug=rwx,o=x file 和 chmod 771 file 同。

[ 本帖最后由 levopat 于 2006-12-18 11:26 编辑 ]


 levopat 回复于:2006-12-18 11:08:11

常用的8进制权限如下:

rwx  对应于  7  <-  1+2+4

--x    对应于  1  
-w-   对应于  2  
r--    对应于  4
rw-   对应于  6  <--  2+4
-wx   对应于  3  <--  1+2



 waker 回复于:2006-12-18 11:12:05

射你一下,加油


 Edengundam 回复于:2006-12-18 11:14:46

引用:原帖由 waker 于 2006-12-18 11:12 发表
射你一下,加油 




...感觉"射"...这个词有点龌龊, 哈哈 :em06:


 levopat 回复于:2006-12-18 11:32:39

十二、更改文件的属主(chown)


语法: chown[-cfhvR] user[:group] file...

注: Unix 是多用户操作系统。利用 chown 可以将文件的拥有者加以改变。一般来说,这个指令只有是由系统管理者(root)所使用,一般使用者没有权限可以改变别人的文件拥有者,也没有权限将自己的文件拥有者改设为别人。


user : 新的文件拥有者的使用者 ID
group : 新的文件拥有者的使用者群体(group)
-c : 若该文件拥有者确实已经更改,才显示其更改动作
-f : 若该文件拥有者无法被更改也不要显示错误讯息
-h : 只对于连结(link)进行变更,而非该 link 真正指向的文件
-v : 显示拥有者变更的详细资料
-R : 对目前目录下的所有文件与子目录进行相同的拥有者变更(即以递回的方式逐个变更)


范例 :

1、将文件 file1.txt 的拥有者设为 users 群体的使用者 pat:

chown pat:users file1.txt


2、将目前目录下的所有文件与子目录的拥有者皆设为 users 群体的使用者 pat:

chmod -R pat:users *



 ganx 回复于:2006-12-18 11:34:31

ssh root@192.168.1.8,然后等到标准输出上出现 “Password:” 将口令输入,从而实现自动登录。
我尝试用here文档和trap来解决,但似乎不行。


 一梦如是 回复于:2006-12-18 12:55:01

请看waker的置顶貼


 levopat 回复于:2006-12-18 14:37:01

引用:原帖由 ganx 于 2006-12-18 11:34 发表
ssh root@192.168.1.8,然后等到标准输出上出现 “Password:” 将口令输入,从而实现自动登录。
我尝试用here文档和trap来解决,但似乎不行。 





需要使用 ssh-keygen



ssh-keygen -t dsa

scp id_dsa root@192.168.0.8:/root/.ssh/

[ 本帖最后由 levopat 于 2006-12-18 15:11 编辑 ]


 pqxpqx 回复于:2006-12-18 15:45:53

看到版主这么辛苦,我也补充一些
grep  的一些常用选项的含义
-c  只是输出一些匹配行的计数
-i  不区别大小写
-l 输出包含匹配的字符文件名
-n 显示匹配的行号
-v 显示不包含匹配的文本所有行
-s 不显示不存在或无匹配文本的错误信息


 kuaizaifeng 回复于:2006-12-18 16:17:03

支持!
学习


 levopat 回复于:2006-12-19 09:32:31

引用:原帖由 pqxpqx 于 2006-12-18 15:45 发表
看到版主这么辛苦,我也补充一些
grep  的一些常用选项的含义
-c  只是输出一些匹配行的计数
-i  不区别大小写
-l 输出包含匹配的字符文件名
-n 显示匹配的行号
-v 显示不包含匹配的文本所有行
-s 不显示不 ... 




多谢,我把他补充到前面的课程中去。


 levopat 回复于:2006-12-19 15:08:26

十二、全屏幕编辑器(vi)


vi(Visual)是以视觉为导向的全屏幕编辑器、共分为三种方式(mode): 

command方式: 
 任何输入都会作为编辑命令,而不会出现在屏幕上,若输入错误则有“jia”的声音;

insert方式: 
 任何输入的数据都置于编辑寄存器。在command方式下输入(I,a,A等),可进入insert方式,insert方式下按ESC,可跳回command方式。 

escape方式: 
以“:”或者“/”为前导的指令,出现在屏幕的最下一行,任何输入都被当成特别指令。 


进入vi(在系统提示符下面输入以下指令): 

vi           进入vi而不读入任何文件 

vi filename      进入vi并读入指定名称的文件(新、旧文件均可)。 



存储及退出vi 

:w filename      存入指定文件,但未退出vi(若未指定文件名则为当前工作的文件名)。 

:wq                        存文件,并且退出vi. 
:q          不作任何修改并退出vi。 
:q!          放弃任何修改并退出vi。 
:!command       暂时退出vi并执行shell指令,执行完毕后再回到vi。 
:sh          暂时退出vi到系统下,结束时按Ctrl + d则回到vi。 


加数据指令 

i           在关标位置开始插入字符,结束时候按ESC键。 

I           在光标所在行的最前面开始加字,结束时按ESC键。 
a           在光标位置后开始加字,结束时按ESC键。 
A           在光标所在行的最后面开始加字,结束时按ESC键。 
o           在光标下加一空白行并开始加字,结束时按ESC键。 
O           在光标上加一空白行并开始加字,结束时按ESC键。 
!command       执行shell指令,并把结果加在光标所在行的下一行。 


删除指令 

nx          删除由光标位置起始的n个字符(含光标位置,按一个x表示删除光标所在的字符) 

nX           删除由光标位置起始的n个字符(不含光标位置)。 
ndw          删除光标位置其实的n个字符组(word)。 
d0           将行的开始到光标位置的字符全部删除。 
d$ 或D         将光标位置起始到行尾的字符全部删除。 
ndd          将光标位置起始的n行(整行)删除(dd表示删除光标所在行)。 
:start,endd      删除文件的第start到end行。 


关标移动 

0           移到一行的开始 

$           移到一行的最后 
[           移到文件开始位置 
]           移到文件结束位置 
nh          往左移n位 
nl或者spacebar     往右移n位 
nk          向上移n行 
n+          向上移n行,光标在该行的起始 
ni           向下移n行 
n-          向下移n行,光标在该行的起始 
H           移到屏幕的左上角 
M           移到屏幕的中间行开头 
L           移到屏幕的最后一行 
G           移到文件的最后一行 
nG或者:n       移到文件的第n行 
nw          右移n个字组,标点符号属于字组 
nW          右移n个字组,标点符号不属于字组 
nb          左移n个字组,标点符号属于字组 
nB          左移n个字组,标点符号不属于字组 

Ctrl + u       屏幕上卷半个菜单 
Ctrl + d        屏幕下卷半个菜单 
Ctrl + b        屏幕上卷一个菜单 
Ctrl + F        屏幕下卷一个菜单 


修改指令 

r           修改光标文件的字符 

R           从光标位置开始修改,结束时按ESC键 
new          更改n组字符,结束时按ESC键 
ncc          从光标所在位置开始更改n行,结束时按ESC键
 

重排各行长度 

i           并按Enter将该行由光标所在处断开,并进入insert方式 

J           把下一行的数据连接到本行之后 


寻找指令 

/text         从光标位置往下找字串text 

?text         从光标位置往上找字串text 
n           继续找下一个字串(在输入上面的寻找指令之后使用)
 

寻找并且取代指令 

:getxt1/s/ /text2/options   将各行的text1替换为text2 

               option=g表示文件中所有的text1均被取代,若未输入任何option,则只有各行中的第一个出现的text1被取代 
               option=go 在屏幕显示各取代的行 
               option=gc 在每个字串取代之前要求确认  
Start,endgtext1/s/ / text2/options  同上,只寻找并取代第start~end行。 
或:Start,ends/text1/text2/options 


复制及移动文件 

:first,last co dest      将first 到last行的数据复制到目标行(dest)下面 

:Start,end m dest      将start 到 end行的数据移动到目标行(dest)下。    
:r filename          将指定文件的内容读入光标所在行下。 
nY               将光标所在位置开始的n行数据暂存 
p               复制暂存数据在光标的下一行 
P               复制暂存数据在光标的上一行 


其他命令 

.               重复前一指令 

u               取消前一指令 
Ctrl + l           刷新屏幕显示 
:set number          显示文件的行号,但不会存文件 
:set nonumber         解除行号显示 
:set ai            设置每行起始位置(以光标当前位置为起始) 
:set noai           取消行起始位置设定 
:f 或<Ctrl> + g        告诉用户有关现行编辑文件的数据。


[ 本帖最后由 levopat 于 2006-12-19 16:21 编辑 ]


 levopat 回复于:2006-12-19 22:46:40

grep 技巧: 输入匹配行的上下文(即输出匹配行的上一行及下一行)

$  grep -B1 -A1 "tty" /etc/passwd

bin:*:3:7:Binaries Commands and Source:/:/sbin/nologin
tty:*:4:65533:Tty Sandbox:/:/sbin/nologin
kmem:*:5:65533:KMem Sandbox:/:/sbin/nologin



 yhong5 回复于:2006-12-20 16:47:15

顶,继续努力


 soaact 回复于:2006-12-20 19:18:48

请问怎么用GREP匹配连续三个相同的字母?
比如:
XXX

谢谢。。。。。。。。。。。。。。。。。。。。。。。。。。。。。


 levopat 回复于:2006-12-21 10:35:18

引用:原帖由 soaact 于 2006-12-20 19:18 发表
请问怎么用GREP匹配连续三个相同的字母?
比如:
XXX

谢谢。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 





# grep "\(.\)\1\1" test.txt


abcfdsfdsfddddd54354499999
aaa
7777

iii



 goodhawk 回复于:2006-12-24 10:33:34

$? 应该是程序是否正常退出。
并不是显示 测试a是否等于4的结果。

九、命令的返回值(SHELL的状态返回值)

当运行一个命令后,SHELL通常会返回一个状态码,该值一般为0或者一个正值
0表示正常运行,即成功。正值一般是运行出错,不同的值是在SHELL内部或内核里面定义的。

例:
ls /
echo $? (显示上一个SHELL的状态返回值)

a=3 (赋值)
test  a = 4 (测试a是否等于4)
echo $? (显示上面测试的结果,0为真(true),正值为假(false)) 

$ a=100
$ test a=101
$ echo $?
0
$ test a=100
$ echo $?
0
$ test_error a=100
test_error: not found
$ echo $?
1


 jobbie1230 回复于:2006-12-25 16:04:38

支持一下,长进不少啊


 levopat 回复于:2006-12-26 09:58:40

引用:原帖由 goodhawk 于 2006-12-24 10:33 发表
$? 应该是程序是否正常退出。
并不是显示 测试a是否等于4的结果。

九、命令的返回值(SHELL的状态返回值)

当运行一个命令后,SHELL通常会返回一个状态码,该值一般为0或者一个正值
0表示正常运行,即成功。 ... 





是我的错, 我查了一下手册:
$?      Expands to the exit status of the most recent pipeline.
         #应该是最近的状态码,与程序运行的逻辑结果无关.


 soaact 回复于:2006-12-27 09:29:47

引用:原帖由 levopat 于 2006-12-21 10:35 发表




# grep "\(.\)\1\1" test.txt


abcfdsfdsfddddd54354499999
aaa
7777

iii
 



谢谢!
您能否能详细讲讲"向前和向后引用"的内容?
期待您的精彩回复.
祝新年快乐!


 levopat 回复于:2006-12-27 10:23:23

十三、字符串操作

${parameter#word}     #它选择最短的匹配,从初始字符串的开始处除去,然后返回结果。
${parameter##word}  #它选择最长的匹配,从初始字符串的开始处除去,然后返回结果。


$ a=helloworld


$ echo ${a#*o}  
world

$ echo ${a##*o}  
rld




${parameter%word}     #它选择最短的匹配,从初始字符串的尾部除去,然后返回结果。
${parameter%%word}  #它选择最长的匹配,从初始字符串的尾部除去,然后返回结果。

$ echo $a

helloworld

$ echo ${a%o}
helloworld

$ echo ${a%o*}
hellow

$ echo ${a%%o*}
hell



 netnat 回复于:2006-12-28 23:32:30

在SHELL里怎么查看某个IP的流量?


 mokai 回复于:2006-12-29 11:05:44

认真看了一下大侠的教程,非常的好。

一直有两个问题没有地方问人,希望楼主帮我解答一下:

一个是关于grep的。
有下面文件名列表:
aa_bb_cc.log
aa_gg.log
ccad_bb_cc.log
test_abcd

我想过滤掉,带两个“_”的文件名,只需要得到带一个"_"和一个"."的文件名。


 levopat 回复于:2007-01-04 08:08:01

引用:原帖由 mokai 于 2006-12-29 11:05 发表
认真看了一下大侠的教程,非常的好。

一直有两个问题没有地方问人,希望楼主帮我解答一下:

一个是关于grep的。
有下面文件名列表:
aa_bb_cc.log
aa_gg.log
ccad_bb_cc.log
test_abcd

我想过滤掉, ... 



根据第十三章,可以做到:

[pat@pat ~/tpm]$ i=aa_bb_cc.log
[pat@pat ~/tpm]$ echo ${i#_}
aa_bb_cc.log
[pat@pat ~/tpm]$ echo ${i#*_}
bb_cc.log
[pat@pat ~/tpm]$ echo ${i##*_}
cc.log


比较  ${i#_} 和 ${i##*_} 是否相同即可


 mokai 回复于:2007-01-04 10:15:14

多谢楼主指点,不过楼主可能误解我的意思了。
我是想用grep过滤下面的文件名。

aa_bb_cc.log
aa_gg.log
ccad_bb_cc.log
test_abcd

都是文件名,如:

ls -1 |grep  -E ""[0-9]\{10,12\}_[0-9]\{6\}.[a-z]\{3,5\}"|"[0-9]\{10,12\}_[0-9]\{6\}.[a-z]\{3,5\}.tar.gz" | grep -E "\.log""

[ 本帖最后由 mokai 于 2007-1-4 10:24 编辑 ]


 levopat 回复于:2007-01-04 15:13:27

引用:原帖由 mokai 于 2007-1-4 10:15 发表
多谢楼主指点,不过楼主可能误解我的意思了。
我是想用grep过滤下面的文件名。

aa_bb_cc.log
aa_gg.log
ccad_bb_cc.log
test_abcd

都是文件名,如:

ls -1 |grep  -E ""[0-9]\{10,12\}_[0 ... 





$ ls -1
aa_bb_cc.log
aa_gg.log
abc_9_.log
abc__.log
abc__log
ccad_bb_cc.log
passwd
test_abcd

$ ls |grep "_.\+_"|grep "\.log"
aa_bb_cc.log
abc_9_.log
ccad_bb_cc.log


[ 本帖最后由 levopat 于 2007-1-4 15:17 编辑 ]


 weismart 回复于:2007-01-04 16:49:36

请问贴主,awk中如何实现向后引用呢?
$ grep "\(.\)\1\1"
1234567   /*这是输入,无输出*/ 
1115555   /*这是输入,111   555都可以*/
1115555   /*这是上面输入的输出*/

下面是awk中使用引后引用
$awk '/\(.\)\1\1/ {print "ok" $0}'
1234567
1115555

没有输出,请问这是为什么呀,郁闷中。


 levopat 回复于:2007-01-05 09:44:18

引用:原帖由 weismart 于 2007-1-4 16:49 发表
请问贴主,awk中如何实现向后引用呢?
$ grep "\(.\)\1\1"
1234567   /*这是输入,无输出*/ 
1115555   /*这是输入,111   555都可以*/
1115555   /*这是上面输入的输出*/

下面是awk中使用引后引 ... 




$ cat a.txt

/usr/local/src/
111222333
2345
222999
44446666

$ sed -n '/\(.\)\1\1\1/p' a.txt
44446666



5.       替代(sub)

字符串替代函数sub,其格式是:

sub (regexp,replacement_string,in_string)

如果替代成功sub函数返回1(true),如果目标字符串没有找到就返回0(false),并且不进行替代。可以在替代字符串中使用保留模式(&),但不能使用向后引用,如\1或\2。

[ 本帖最后由 levopat 于 2007-1-5 10:04 编辑 ]


 levopat 回复于:2007-01-09 15:15:46

最近时间有限,而且准备在另一版写一个C语言的入门篇。如果大家有什么问题,贴上,我还会关注此贴的。




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=865910
转载请注明作者名及原文出处