shell学习笔记

shell学习笔记  



1、查看/etc/shells,看看有几个可用的Shell



2、 曾经用过的命令存在.bash_history中,但是~/.bash_history记录的是前一次登录前记录的所有指令,成功登出后,才存到 .bash_history中。



5、man bash查看bash说明文件。



6、echo $ 



7、变量的设定中,单引号与双引号的不同:双引号仍然可以保留变量的内容,单引号内只能是一般字符,不会有特殊符号。



8、反单引号`符号:在一串指令中,在`之内的指令都会被先执行,而其执行出来的结果将作为外部的输入内容。



9set:显示bash内的变量。



10、$:代表目前这个SHELL的执行者代码(PID)。echo $$ 出现的数字就是PID号码。



11、?:上一个指令所回传的值。0或者非0值:  echo $?



12、目前个人电脑的CPU分为:32/64位,其中32位分i386、i586、i686,而64位则称为x86_64。



13、子程序仅会继承父程序的环境变量,不会继承父程序的自定义变量。



14、export 变量名称:分享自己的变量设定给后来启动的程序。



15、locale:列出系统所支持的所有语言。



16、read:读取键盘变量



17、declare、typeset:定义变量类型



18、限制使用者的某些系统资源:ulimit



19、#:符合取代文字的 最短的 那一个



20、##:符合取代文字的 最长的 那一个



21、%:从后面向前删除变量内容



22、命令别名定义:alias,unalias(例如:定义alias lm='ls -al | more'23、历史命令:history



24、bash shell的操作环境:



例題:



設定 echo 的命令別名成為 echo -n ,然後再觀察 echo 執行的順序



答:



[root@www ~]# alias echo='echo -n'[root@www ~]# type -a echoecho is aliased to `echo -n'echo is a shell builtinecho is /bin/echo



瞧!很清楚吧!先 alias 再 builtin 再由 $PATH 找到 /bin/echo 囉!  



25、bash的进站欢迎信息:/etc/issue,/etc/motd



26、login shell整体环境的设定:/etc/profile



27、source:读取环境设定的命令



28、默认的bash设定:~/.bashrc



29、Bash shell组合键:

組合按鍵    執行結果

Ctrl + C    終止目前的命令

Ctrl + D    輸入結束 (EOF),例如郵件結束的時候;

Ctrl + M    就是 Enter 啦!

Ctrl + S    暫停螢幕的輸出

Ctrl + Q    恢復螢幕的輸出

Ctrl + U    在提示字元下,將整列命令刪除

Ctrl + Z    『暫停』目前的命令



30、特殊符号:

符號    意義

*    代表『 0 個到無窮多個』任意字元

?    代表『一定有一個』任意字元

[ ]    同樣代表『一定有一個在括號內』的字元(非任意字元)。例如 [abcd] 代表『一定有一個字元, 可能是 a, b, c, d 這四個任何一個』

[ - ]    若有減號在中括號內時,代表『在編碼順序內的所有字元』。例如 [0-9] 代表 09 之間的所有數字,因為數字的語系編碼是連續的!

[^ ]    若中括號內的第一個字元為指數符號 (^) ,那表示『反向選擇』,例如 [^abc] 代表 一定有一個字元,只要是非 a, b, c 的其他字元就接受的意思。

符號    內容

#    註解符號:這個最常被使用在 script 當中,視為說明!在後的資料均不執行

     跳脫符號:將『特殊字元或萬用字元』還原成一般字元

|    管線 (pipe):分隔兩個管線命令的界定(後兩節介紹);

;    連續指令下達分隔符號:連續性命令的界定 (注意!與管線命令並不相同)

~    使用者的家目錄

$    取用變數前置字元:亦即是變數之前需要加的變數取代值

&    工作控制 (job control):將指令變成背景下工作

!    邏輯運算意義上的『非』 not 的意思!

/    目錄符號:路徑分隔的符號

>, >>    資料流重導向:輸出導向,分別是『取代』與『累加』

<, <<    資料流重導向:輸入導向 (這兩個留待下節介紹)

' '    單引號,不具有變數置換的功能

" "    具有變數置換的功能!

` `    兩個『 ` 』中間為可以先執行的指令,亦可使用 $( )

( )    在中間為子 shell 的起始與結束

{ }    在中間為命令區塊的組合!



31、/dev/null 垃圾桶黑洞 

32、eof:输入这个关键字,立刻结束,不需输入[ctrl]+d

33、>与>>

34、命令执行的判断依据:        ;    ,    &&    ||

35、cut、grep:拾取命令

36、排序命令:sort、wc、uniq

37、tee

38、字符转换命令:tr,col,join.paste,expand

39、分割命令:split

40、参数替换:xargs

41、减号"-"的用途

4)如果读取到一个Enter符号(CR),就会尝试开始执行该行命令,

5)如果一行内容太多,可使用  \来延伸至下一行,

6)# 可作为注解。





1、>file  前面没有命令,shell会创建一个空文件(长度为0个字符),如果文件以前已经存在,其内容就会丢失。 

2、一行中可以键入多条命令,命令之间用分号分隔。 

3、如果在键入的命令之后跟一个&符号,该命令就发送到后台执行,也就是说,该命令不再占住终端,可以继续处理其他工作。 

4、$字符是shell的特殊字符,如果$后跟一个合法的变量名,shell会把它当作在此处用变量所存储的值来替换的指令。表达式可以写为$((expression))。 

5、shell变量$#,里面存的是命令行中所键入的参数个数。 

6、$*可以引用传递给程序的所有的参数,在参数不确定或者参数数目可变的程序中,通常是很有用的。 



7. "$@" 它会被替换成“$n”,这里$@前后的双引号是必不可少的,如果没有,变量$@和$*完全一样。 

7、如果要给一个程序传递9个以上的参数,不能用$10、$11的方法来取第10个以及以后的参数,要用${n}这种格式。 

8、shell自动将最后所执行命令的退出状态设置到shell变量$?中。 

    $cp phonebook phone2 

    $echo $? 

    $0 

    0操作成功 非0操作失败 

 

9、内部命令test,它用来在if命令中测试一种或几种条件,格式为 test expression。 

    -n string 检测string不为空为真 

    -n string 检测string为空为真 

   test命令的另外一种模式[expression] 

    -eq 等于 

    -ge 大于等于 

    -gt 大于 

    -le 小于等于 

    -lt 小于 

    -ne 不等于 

   文件判断 

    -d  为目录  

    -e  存在 

    -f  普通文件 

    -r  可读文件 

    -s  长度不为0 

    -w  可写文件 

    -x  可执行文件 

    -L  链接文件 

   逻辑判断  

    !   逻辑非 

    -a  逻辑与 

    -o  逻辑或 

 

10、小括号格式 (  ) 

11、else结构 

    if command1 

    then 

       command 

    else 

       command 

    fi 

12、内部命令exit 它可以立即终止shell程序的执行。exit n  n为希望返回的退出状态,不指定为最后一条命令的退出状态。 



13、elif结构 

    if command1 

    then 

       command 

    elif command2 

       then 

         command 

    else 

       command 

    fi 

 

14、case结构 

    case value in 

    pat1)  command 

           command 

        ... 

           command;; 

 

    pat2)  command 

           command 

        ... 

           command;; 

    ... 

    patn)  command 

           command 

        ... 

           command;; 



    *)

    esac 

 

    case语句中的特殊字符指定匹配模式: 

        ?表示任一个字符 

        *表示0或若干个任意字符一个,最后的“*)”表示默认模式,当使用前面的各种模式均无法匹配该变量时,将执行“*)”后的命令序列。





15、-x 调试程序选项 

    sh -x 程序名 程序参数 

 

16、空命令  : 

    其目的是什么也不做,多用于条件语句 

 

17、&&和||结构 

    &&       如果在任何需要shell命令的位置写了 command1 && command2 则先执行command1,如果返回的退出状态为0则执行command2;如果command1返回的退出状态不为0,则跳过command2。 

    ||       结构功能也差不多,区别在于只有当第一条命令的退出状态不为0时才执行第二条命令。 

    在这种结构的左右两边都可以用管道线。如果用在左边,检测的是管道线中最后一条命令的退出状态。 

 

18、for命令

    for var in  word1 word2 ...  wordn/filenames[1-n]/$* 

    do 

        command 

        command 

        ... 

    done 

 

19、while命令 

    while command1 

    do  

        command 

        command 

        ... 

    done 

while 经常与shift命令共同使用。shift命令使位置变量向下移(即$n到$n-1),并且$#递减。 

 

20、until命令 

    until command1 

    do 

        command 

        command 

        ... 

    done 

与while模式相反 

 

21、sleep n 程序挂起n秒,  



  's' for seconds (the default),

       'm' for minutes,



  'h' for hours,



  'd' for days.

22break n、continue n从n层循环中退出 

23、PATH  执行命令时shell要搜索的目录,这些目录彼此之间用冒号{:}分隔 

24、exec 命令      exec program  以新shell代替当前程序 

 

touch命令改变文件的时间信息。

参数:

-a : 仅修改access time。

-c : 仅修改时间,而不建立文件。

-r : 参照某个文件的时间记录。

-t : 后面可以接时间,格式为 [[CC]YY]MMDDhhmm[.SS] 如198408250310.20

 -d, --date=STRING

              parse STRING and use it instead of current time

-f     (ignored)

-h, --no-dereference

              affect each symbolic link instead of any referenced file (useful

              only on systems that can change the timestamps of a symlink)

-m     change only the modification time

-r, --reference=FILE

              use this file's times instead of current time

-t STAMP

              use [[CC]YY]MMDDhhmm[.ss] instead of current time

--time=WORD

              change the specified time: WORD is access, atime, or use: equiv-

              alent to -a WORD is modify or mtime: equivalent to -m

--help display this help and exit

--version

              output version information and exit

       Note that the -d and -t options accept different time-date formats.
function show

{

    echo $1$2;

}

H="Hello,,,"

W="World!!!!"

# 调用函数,并传给两个参数H和W

show $H $W

cut, expr, sed, awk

cut -d : -f 1,5 /etc/passwd

正则表达式:
\ 关闭或者打开后续字符的特殊意义 . 匹配任何单个字符,初NUL外
* 匹配在它之前的任何数目的单个字符 + 1个或多个(ERE only) ? 0个或多个(ERE only) ^ 表示一行的开始,在[^...]里面表示取反 $ 表示一行的结尾 [...] 匹配方括号内的任一单个字符 {n} 匹配前面单个字符出现n次(ERE,在BRE中需要使用转义\{n\}) {n,m} 出现至少n次,最多m次 () 表示一个实例(ERE only) | 匹配之前或之后的正则表达式(ERE only)

 

5. 向后引用: backreferences

如,\(ab\)\(cd\)[def]*\2\1 可以匹配abcdcdab, abcdeeecdab, abcdffcdab, ...向后引用最多可以有9个



6. POSIX字符集: [:alpha:]

[:alnum:]  数字字符,如123

[:alpha:]  字母字符,如abcDEF

[:lower:]  小写字母字符,如abc

[:upper:]  大写字母字符,如DEF

[:blank:]  空格space于定位tab字符

……更多

$ grep -E ^[[:alpha:]]\{3\} data.txt

hello, world.

abcDEFdefABC



7. ERE(Extended RE)

没有向后引用。

区间表达不需要\{\},直接使用abc{3,5},表示c出现3到5次

?  表示0个或一个前置RE

+  1个或多个

*  与BRE相同,0个或多个

|  交替,匹配这个序列或那个序列或... read|write|listen

() 分组,(abc){3,5}表示abc出现3到5次,但不包括括号()本身,



8. 额外的GNU正则表达式运算符: \w

\w  匹配任何单词组成的字符

\W  匹配任何非单词组成的字符,^\w



9. 进行文本查找替换: sed(steam editor)

sed s/regexp/replacement/

$ sed 's/:.*/:******/' data.txt

hello, world.

abcDEFdefABC

password:******

another password:******

上面命令把冒号(:)后面的所有内容替换成6个星号(*),sed s/regexp/replacement/中的/作为一个定界符,任何可以显示的字符都可以,如

sed s;regexp;replacement;

sed s:regexp:replacement:

sed s,regexp,replacement,

……等

$ find /home/owen/test/todelete/ -type d -print |

sed 's;/home/owen/test/todelete;/home/owen/test/todel;' |

sed 's/^/mkdir /' |

sh -x

+ mkdir /home/owen/test/todel/

+ mkdir /home/owen/test/todel/xyz

该命令首先找出/home/owen/test/todelete/这个目录下的所有目录,包括这个目录自身,然后把todelete替换成todel,得到如下结果:

/home/owen/test/todel/

/home/owen/test/todel/xyz

然后在每行前面加上"mkdir "命令创建新的目录。所实现的功能类似cp。



10. 查看系统的密码信息: /etc/passwd

$ more /etc/passwd

owen:x:1000:1000:owen,,,:/home/owen:/bin/bash

每行都是以:分隔的7个字段,分别表示

owen 用户名称

x  加密后的密码

1000  用户ID编号

1000  用户组ID编号

owen,,,  用户姓名,附加其他信息,如联系方式等

/home/owen  用户的根目录

/bin/bash  登录的shell类型



11. 从文本中剪贴部分内容: cut

$ cut -d : -f 1,5 /etc/passwd | grep -E ^m

man:man

mail:mail

messagebus:

mysql:MySQL Server,,,

-d 表示分割符,-f 表示field



12. 连接2个文件,基于字段:join

join quotas.sorted sales.sorted

使用两个文件中第一个字段进行连接,如

quotas.sorted

a b

sales.sorted

a c

连接之后,为a b c

当然可以指定连接的key, -1 2 -2 5, 参考manual



13. 重新编排字段: awk

$ ls -l | awk '{ print $8, $5, $1}' | sort

data.txt 67 -rw-r--r--

finduser 88 -rwxr-xr-x

merge-sales.sh 363 -rwxr-xr-x

note.sh 36 -rwxr-xr-x

nusers 60 -rwxr-xr-x

quotas 58 -rw-r--r--

sales 71 -rw-r--r--

  total

这里先列出当前目录下的文件,然后使用awk显示文件名,大小,权限,最后进行排序显示。

awk默认使用空格作为分隔字符。

$ ls -l | awk '{ printf "%s %s\t %s\n", $1, $5, $8}' | sort

其基本模式如下:



#chapter 4 text process tools



14. 文本排序: sort

$ sort -t : -k 3,3 /etc/passwd

-t指定分隔符,-k指定从哪个字段到哪个字段作为key进行排序



15. 去除重复: uniq

$ sort uniq-data | uniq -c

      2 duo

      3 tres

      1 unus

消除重复,可以控制显示重复的或是未重复的记录



16. 简单的文本格式化命令: fmt

$ more data.txt | fmt -w 50

hello, world.  abcDEFdefABC password:123456

another password:666888



string sort\nbased on lines delimilated by new

line sign

格式化成每行最多50个字符



17. 计算行数、字数和字符数: wc

/usr/share/dict$ more words | grep ^herb | wc -lwc

     17      17     165



18. 查看标准输入的前n条记录,或是文件列表中的前n条,或后n条: head, tail

head -n 5 /etc/passwd

sed -e 5q /etc/passwd

显示倒数n条,一般用来查看最近的日志记录

tail -n 5 /etc/passwd



#chapter 5 the magic power of pipe



19. 文字解谜好帮手puzzle-help.sh文件: example

FILES="

        /usr/dict/words

        /usr/share/dict/words

      "

pattern="$1"

egrep -h -i "$pattern" $FILES 2> /dev/null | sort -u -f

使用这个脚本来进行查找具有10个字母的单词,以b开头,第7位不是x就是y:

$ sh puzzle-help.sh '^b.{5}[xy].{3}$' | fmt

beatifying Birdseye's blarneying Brooklyn's Bulawayo's

等价于使用命令:

/usr/share/dict$ more words | egrep -i  '^b.{5}[xy].{3}$'| sort

beatifying

Birdseye's

blarneying

Brooklyn's

Bulawayo's



20. 转换或者删除字符:tr

tr [ options ] source-char-list replace-char-list

-c 取source-char-list的反义,即对没有出现在source-char-list中的字符进行转换或删除

-d 删除source-char-list里出现的字符,如删除所有元音字母:

echo hello world | tr -d [aeiou]

hll wrld

-s 浓缩重复的字符,如:

echo hello world | tr -s l

helo world

一般会组合来使用,如全部转换成小写字符,所有非字母字符转换成换行符号

echo heLLo WorLd  123 End | tr A-Z a-z | tr -cs A-Za-z '\n'

hello

world

end

这里没有包括数字,如果需要包括,则添加A-Za-z0-9就可以了



21. 统计一篇文章中单词出现频率: wf

tr -cs A-Za-z0-9 '\n' |     将非字母字符转换成换行符号,-cs参考第20条笔记

  tr A-Z a-z |              全部转换成小写字母

    sort |                  排序

      uniq -c |             统计频率,结果: 13 the等

        sort -k1,1nr -k2 |  首先只取第一个field即数字,按照数字顺序-n逆序-r排序,再对单词以字典顺序排序

          sed ${1:-25}q     ${1}获取命令行的第一个参数,如果没有默认为25,后面q表示退出程序



${1:-25}是shell里面的一个参数展开形式,具体如下:

${var:-default-var}

展开方式是:首先查找${var},如果找到,值就为${var},如果没有找到,值就等于default-var



使用(需要chmod +x wf,然后把wf放到$PATH路径下),使用频率最高的:

man awk | wf | pr -c4 -t -w80

    292 the             69 are             50 0             40 mawk

    169 and             69 string       49 s             40 n

    168 is             65 1               48 expr       39 be

    155 a               64 if             45 as         38 awk

    124 of             52 for             45 or         38 file

    118 to             52 with         40 an         38 i

     80 in

pr命令,打印格式化,page column for printing

-c4 表示column4,相当于word的分栏操作,这里设置为4栏

-t  表示不显示页头和页尾,如果没有这个,就是一张打印纸那么大

-w80  设置页面宽度,这里是80个字符



最低的呢:

$ man awk | wf 99999 | tail -n 25 | pr -c4 -t -w80

      1 typically         1 under          1 values              1 wc

      1 u                    1 underscores 1 variations        1 we

      1 unaltered         1 unlike        1 variety              1 whidbey

      1 unambiguous       1 unnecessary 1 vdiesp              1 writing

      1 unbuffered        1 unsafe        1 vertical          1 xaxbxcx

      1 unchanged         1 usually        1 via                  1 xhh

      1 undefined

我的path

echo $PATH

/home/owen/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin



这个程序比较有意思,我们可以算出awk手册里使用了多少个不重复的单词,才1014个,99999这个数没有实际意义,只是很大而已

$ man awk | wf 99999 | wc -l

1014



高频词汇(频率在5次以上,包括5次)个数,尽然是这么得少!

$ man awk | wf 99999 | awk '$1 >= 5' | wc -l

220



22. 学以致用: 标记和自动目录生成

$ more shell笔记.txt | grep -E '#'



#chapter 2 shell basic

#chapter 3 search and substitution

#chapter 4 text process tools

#chapter 5 the magic power of pipe



more shell笔记.txt | grep -E '^[0-9]+\.' | sed 's/^/@-/'

@-1. 访问脚本从命令行接收到的参数:$n

@-2. 在shell脚本执行时,使用-x打开脚本执行跟踪功能。如: $ sh -x nusers.sh

@-3. 列出系统所支持的所有语言: locale -a

@-4. shell BRE(Basic RE) and ERE(Extended RE)正则表达式简记:

@-5. 向后引用: backreferences

@-6. POSIX字符集: [:alpha:]

@-7. ERE(Extended RE)

@-8. 额外的GNU正则表达式运算符: \w

@-9. 进行文本查找替换: sed(steam editor)

@-10. 查看系统的密码信息: /etc/passwd

@-11. 从文本中剪贴部分内容: cut

@-12. 连接2个文件,基于字段:join

@-13. 重新编排字段: awk

@-14. 文本排序: sort

@-15. 去除重复: uniq

@-16. 简单的文本格式化命令: fmt

@-17. 计算行数、字数和字符数: wc

@-18. 查看标准输入的前n条记录,或是文件列表中的前n条,或后n条: head, tail

@-19. 文字解谜好帮手puzzle-help.sh文件: example

@-20. 转换或者删除字符:tr

@-21. 统计一篇文章中单词出现频率: wf

@-22. 学以致用: 标记和自动目录生成



使用sed命令给每条数据添加一个@-前缀,以便与真正的目录混淆。







#chapter 6 variables, repetitions



23. 设置或修改环境变量: export

PATH=$PATH:/home/owen/bin

export PATH

打印环境变量export -p



24. 从shell中删除变量于函数: unset

$ foo=123

$ echo $foo

123

$ unset foo

$ echo $foo

使用unset -f function_name删除函数,默认为-v即删除变量



25. 参数展开: ${varname:-word}

替换运算:

${varname:-word}  如果varname存在且非Null,则返回其值;否则返回word。用途: 如果变量未定义,则使用默认值



${varname:=word}  如果varname存在且非Null,则返回其值;否则设置它的值为word,并返回其值。用途: 如果变量未定义,则设置变量为默认值



${varname:+word}  如果varname存在且非Null,则返回word;否则返回null。用途: 为测试变量的存在。



${varname:?message}  如果varname存在且非Null,则返回其值;否则显示varname:message,并退出当前命令或脚本。用途: 捕捉由于变量未定义所导致的错误

$ echo ${vars:?"undefined, pls check it"}

bash: vars: undefined, pls check it



注意上面的${varname:-word}每个冒号(:)都是可选的,如果没有冒号,条件变为“如果varname存在”,也就是可以为空



更多模式匹配

$ p=/home/jwu/cases/long.file.name

$ echo $p

/home/jwu/cases/long.file.name



${variable#pattern}  如果模式匹配于变量的开头处,则删除匹配的最短部分,返回剩下的部分

$ echo ${p#/*/}

jwu/cases/long.file.name



${variable##pattern}  如果模式匹配于变量的开头处,则删除匹配的最长部分,返回剩下的部分

$ echo ${p##/*/}

long.file.name



${variable%pattern}  如果模式匹配于变量的结尾处,则删除匹配的最短部分,返回剩下的部分

$ echo ${p%.*}

/home/jwu/cases/long.file



${variable%%pattern}  如果模式匹配于变量的结尾处,则删除匹配的最长部分,返回剩下的部分

$ echo ${p%%.*}

/home/jwu/cases/long



注意,这里使用的pattern,以及shell里其他的地方,如case语句等,不同于前面正则表达式的模式匹配。如上,这里*代表任何一个符号,而.只代表点号本身。



26. POSIX标准化字符从长度运算符: ${#variable}返回$variable值的长度

$ d=diversification

$ echo $d

diversification

$ echo ${#d}

15



27. shell特殊变量,访问参数: $#, $@, $*

设置参数: $ set -- hello "hi there" greeting

$#  传递到shell脚本或函数的参数总数

$@  传递进来的命令行参数,置于双引号("")内,会展开为个别的参数

$ for i in $@

> do echo i is $i

> done

i is hello

i is hi

i is there

i is greeting

注意上面的hi there之间的空格丢失了

$ for i in "$@"

> do echo i is $i

> done

i is hello

i is hi there

i is greeting

加上""会得到每个参数

$*  传递进来的命令行参数,置于双引号("")内,会展开为一个单独的参数



28. shell运算符与C语言类似: + - * /

运算置于$((...))之内,注意是圆括号

具体参考运算表

例:

$((3 && 2))

1

$ echo $((3 > 2))

1

$ echo $((3 > 4))

0

$ echo $(( (3 > 2) || (3 > 4) ))

1

与C及其衍生语言C++, Java, and awk等相同,非0值表示true。



29. 退出状态: $?

$ echo hello

hello

$ echo $?

0

$ e s

e: command not found

$ echo $?

127

POSIX的结束状态

0    命令成功退出

其他状态都是失败退出,如

127  命令找不到



可以在shell脚本中传递一个退出值给它的调用者,如exit 42



30. 判断语句: if-elif-else-fi

if pipeline

then ...

elif pipeline

then ...

else ...

fi



31. 逻辑判断: NOT, AND, OR

NOT  if ! (...)

AND  (...) && (...)

OR   (...) || (...)



32. test命令: if...

if [ $# -ne 1 ]

then

  echo Usage: finduser username >&2

  exit 1

fi

主要的数字比较有

-eq  equal

-ne  not equal

-lt  less than

-gt  great than

-le  less or equal

-ge  great or equal



#chapter 7 input/output, file, and commands execute



    to be continue...

 

join用来将来自两个分类文本文件的行连在一起。下面讲述join工作方式。这里有两个文件file1和file2,当然已经分类。每个文件里都有一些元素与另一个文件相关。由于这种关系,join将两个文件连在一起,这有点像修改一个主文件,使之包含两个文件里的共同元素。文本文件中的域通常由空格或tab键分隔,但如果愿意,可以指定其他的域分隔符。类似于数据库中的join。

其一般格式为:

join [options] input-file1 input-file2

让我们看看它的可用选项列表:

an n为一数字,用于连接时从文件n中显示不匹配行。例如, -a1显示第一个文件的不匹配行,-a2为从第二个文件中显示不匹配行。

o n.m n为文件号,m为域号。1.3表示只显示文件1第三域,每个n,m必须用逗号分隔,如1.32.1。

j n m n为文件号,m为域号。使用其他域做连接域。

t 域分隔符。用来设置非空格或tab键的域分隔符。例如,指定冒号做域分隔符-t:

例子:

wangnc> pg name.txt

M.Golls 12 Hidd Rd

P.Heller The Acre

P.Willey 132 The Grove

T.Norms 84 Connaught Rd

K.Fletch 12 Woodlea

wangnc> pg town.txt

M.Golls Norwich NRD

P.Willey Galashiels GDD

T.Norms Brandon BSL

K.Fletch Mildenhall MAF

wangnc>

连接两个文件,使得名字支持详细地址。例如M . G o l l s记录指出地址为12 Hidd Rd。连接域为域0—名字域。因为两个文件此域相同, join将假定这是连接域:

wangnc> join name.txt town.txt

M.Golls 12 Hidd Rd Norwich NRD

P.Willey 132 The Grove Galashiels GDD

T.Norms 84 Connaught Rd Brandon BSL

K.Fletch 12 Woodlea Mildenhall MAF

好,工作完成。缺省join删除或去除连接键的第二次重复出现,这里即为名字域。

如果一个文件与另一个文件没有匹配域时怎么办?这时join不可以没有参数选项,经常指定两个文件的- a选项。下面的例子显示匹配及不匹配域。

wangnc> join -a1 -a2 name.txt town.txt

M.Golls 12 Hidd Rd Norwich NRD

P.Heller The Acre

P.Willey 132 The Grove Galashiels GDD

T.Norms 84 Connaught Rd Brandon BSL

K.Fletch 12 Woodlea Mildenhall MAF

使用- o选项选择连接域。例如要创建一个文件仅包含人名及城镇, join执行时需要指定显示域。方式如下:

使用1 . 1显示第一个文件第一个域,2 . 2显示第二个文件第二个域,其间用逗号分隔。命令为:

wangnc> join -o 1.1,2.2 name.txt town.txt

M.Golls Norwich

P.Willey Galashiels

T.Norms Brandon

K.Fletch Mildenhall

使用-jn m进行其他域连接,例如用文件1域3和文件2域2做连接键,命令为:

join -j1 3 -j2 2 file1 file2

使用join应注意连接域到底是哪一个,比如说你认为正在访问域4,但实际上join应该访问域5,这样将不返回任何结果。如果是这样,用awk检查域号。

例如,键入$awk '{print $4}'文件名,观察其是否匹配假想域。









sed是一个强大的文本过滤工具。使用sed可以从文件或字符串中抽取所需信息。

sed是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。Vi也是一个文本编辑器。sed可以随意编辑小或大的文件,有许多sed命令用来编辑、删除,并允许做这项工作时不在现场。sed一次性处理所有改变,因而变得很有效,对用户来讲,最重要的是节省了时间。使用sed需要记住的一个重要事实是,无论命令是什么, sed并不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕。

打印第2行:(p表示显示行,-n表示只显示匹配行)

sed -n '2p' data.f

现打印1到3行,用逗号分隔行号:

sed -n '1,3p' data.f

模式匹配行:

sed -n '/USP/'p data.f 同 awk '$0~/USP/' data.f

使用4,/USP/。意即只在第四行查询模式the:???

sed -n '4,/USP/'p data.f

要打印整个文件,只需将行范围设为第一行到最后一行1 , $。$意为最后一行:

sed -n '1,$p' data.f

要打印文件第一行,使用行号:

sed -n '1p' data.f

要打印最后一行,使用$。$是代表最后一行的元字符:

sed -n '$p' data.f

要打印行号,使用等号=。打印模式匹配的行号,使用格式/pattern/ =

sed -n '/USP/=' data.f

打印模式匹配的行号及其所有内容,使用-e

sed -e '/USP/=' data.f

如果只打印行号及匹配行,必须使用两个sed命令,并使用e选项。第一个命令打印模式匹配行,第二个使用=选项打印行号,格式为sed -n -e /pattern/p -e /pattern/=

sed -n -e '/USP/p' -e '/USP/=' data.f

sed 's/Unix/UNIX/' file     将第一个Unix换成UNIX
sed 's/Unix?UNIX/' file      将所有的Unix换成UNIX
sed -n '1,2p' file             只显示前两行
sed -n '/UNIX/p' file        只打印包含UNIX的行
sed '1,2d' file                删除第一行和第二行
sed '/UNIX/d' file            删除包含UNIX的各行
sed '5d'                    删除第5行
sed '/[Tt]est/d'            删除包含test或ZTest的行
sed -n '20,25p' file        只显示文件file的第20行到第25行
sed '1,10s/unix/UNIX/g' file 把file前10行中的unix改为UNIX
sed '/jan/s/-1/-5/'            将所有包含jan的行中第1个-1改为-5
sed 's/...//' file            删除file文件每一行的前3个字符
sed 's/...$//' file            删除data文件每一行的最后3个字符 sort命令的一般格式为: sort
-cmu -o output_file [other options] +pos1 +pos2 input_files 下面简要介绍一下sort的参数: -c 测试文件是否已经分类。 -m 合并两个分类文件。 -u 删除所有复制行。 -o 存储sort结果的输出文件名。 其他选项有: -b 使用域进行分类时,忽略第一个空格。 -n 指定分类是域上的数字分类。 -t 域分隔符;用非空格或tab键分隔域。 -r 对分类次序或比较求逆。 +n n为域号。使用此域号开始分类。 n n为域号。在分类比较时忽略此域,一般与+n一起使用。 post1 传递到m,n。m为域号,n为开始分类字符数;例如4,6意即以第5域分类,从第7个字符开始。 最基本的sort方式为sort filename,按第一域进行分类(分类键0)。实际上读文件时sort操作将行中各域进行比较,这里返回基于第一域sort的结果: sort -t: /etc/passwd > passwd.bak 如果要逆向sort结果,使用- r选项。在通读大的注册文件时,使用逆向sort很方便。下面是按域0分类的逆向结果: sort -t: -r /etc/passwd > passwd.bak 有时需要只按第2域(分类键1)分类。这里为重排报文中供应区代码,使用t 1,意义为按分类键1分类: sort -t: +1 /etc/passwd > passwd.bak 如果是数值域,即为数值分类,可以使用- n选项: sort -t: +2n /etc/passwd > passwd.bak 有时,原文件中有重复行,这时可以使用- u选项进行唯一性(不重复)分类以去除重复行: sort -u /etc/passwd > passwd.bak 可以指定分类键次序。先以第4域,再以第1域分类,命令为-k4 -k1 sort -t: -k4 -k1 /etc/passwd > passwd.bak sort还可以用于d f命令,以递减顺序打印使用列下面是按占用空间百分比,第4+1域) df | sort -r +4 split用来将大文件分割成小文件。有时文件越来越大,传送这些文件时,首先将其分割可能更容易。使用vi或其他工具诸如sort时,如果文件对于工作缓冲区太大,也会存在一些问题。因此有时没有选择余地,必须将文件分割成小的碎片。 split命令一般格式: split -output_file-size input-filename output-filename 这里output-file-size指的是文本文件被分割的行数。split查看文件时,output-file-size选项指定将文件按每个最多1000行分割。如果有个文件有2800行,那么将分割成3个文件,分别有1000、1000、800行。每个文件格式为x[aa]到x[zz],x为文件名首字母, [aa]、[zz]为文件名剩余部分顺序字符组合。 例子: test> ll total 81 -rw-rw-r-- 1 wangnc users 82029 Aug 24 16:28 myfile test> wc -l myfile 2082 myfile test> split myfile test> ll total 162 -rw-rw-r-- 1 wangnc users 82029 Aug 24 16:28 myfile -rw-rw-r-- 1 wangnc users 39633 Aug 24 16:29 xaa -rw-rw-r-- 1 wangnc users 40481 Aug 24 16:29 xab -rw-rw-r-- 1 wangnc users 1915 Aug 24 16:29 xac 按每个文件2行分割,命令为: mydir3> ls myfile mydir3> wc -l myfile 2 myfile mydir3> vi myfile mydir3> mydir3> wc -l myfile 7 myfile mydir3> split -2 myfile mydir3> ll total 5 -rw-rw-r-- 1 wangnc users 102 Aug 24 16:33 myfile -rw-rw-r-- 1 wangnc users 29 Aug 24 16:33 xaa -rw-rw-r-- 1 wangnc users 29 Aug 24 16:33 xab -rw-rw-r-- 1 wangnc users 30 Aug 24 16:33 xac -rw-rw-r-- 1 wangnc users 14 Aug 24 16:33 xad 用户可以使用shell脚本创建交互性的、专业性强的屏幕输出。要实现这一点,系统上需要一个彩色监视器和tput命令。tput使用文件/etc/terminfo或/etc/termcap,这样就可以在脚本中使用终端支持的大部分命令了。 在使用tput前,需要在脚本或命令行中使用tput命令初始化终端。 $ tput init tput产生三种不同的输出:字符型、数字型和布尔型(真/假)。 下面是大部分常用字符串: bel 警铃 blink 闪烁模式 bold 粗体 civis 隐藏光标 clear 清屏 cnorm 不隐藏光标 cup 移动光标到屏幕位置( x,y) el 清除到行尾 ell 清除到行首 smso 启动突出模式 rmso 停止突出模式 smul 开始下划线模式 rmul 结束下划线模式 sc 保存当前光标位置 rc 恢复光标到最后保存位置 sgr0 正常屏幕 rev 逆转视图 以下是大部分常用数字输出: cols 列数目 it tab设置宽度 lines 屏幕行数 在tput中只有两种布尔操作符: chts 光标不可见 hs 具有状态行 tr用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。 带有最常用选项的tr命令格式为: tr -c -d -s ["string1_to_translate_from"] ["string2_to_translate_to"] input-file 这里: -c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。 -d 删除字符串1中所有输入字符。 -s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。 Input-file是转换文件名。虽然可以使用其他格式输入,但这种格式最常用。 例子: wangnc> pg oops.txt And the cowwwwws went homeeeeeeee Or did theyyyy 如果要去除重复字母或将其压缩在一起,使用- s选项。因为都是字母,故使用[a-z]。输入文件重定向到tr命令。 wangnc> tr -s "[a-z]" echo "May Day,May Day,Going Down.." | tr "[a-z]" "[A-Z]" MAY DAY,MAY DAY,GOING DOWN.. wangnc> echo "May Day,May Day,Going Down.." | tr "[A-Z]" "[a-z]" may day,may day,going down.. 将文本文件从小写转换为大写并将结果存入一个新文件,格式为: cat file-to-translate | tr "[a-z]" "[A-Z]" > new-file-name 命令tr -cs "[a-z][A-Z]" "[\012*]"将文件每行所有不包含在[a-z]或[A-Z](所有希腊字母)的字符串放在字符串1中并转换为一新行。-s选项表明压缩所有新行, -c表明保留所有字母不动。 tr的第一个功能就是转换控制字符,特别是从dos向UNIX下载文件时,忘记设置ftp关于回车换行转换的选项时更是如此。 如果需要删除文件中^M,并代之以换行。使用命令: tr -s "[\015]" "\n" uniq用来从一个文本文件中去除或禁止重复行。可以认为uniq有点像sort命令中唯一性选项。对,在某种程度上讲正是如此,但两者有一个重要区别。sort的唯一性选项去除所有重复行,而uniq命令并不这样做。重复行是什么?在uniq里意即持续不断重复出现的行,中间不夹杂任何其他文本. 命令一般格式: uniq -u d c -f input-file output-file 其选项含义: -u 只显示不重复行。 -d 只显示有重复数据行,每种重复行只显示其中一行 -c 打印每一重复行出现次数。 -f n为数字,前n个域被忽略。 一些系统不识别-f选项,这时替代使用-n。 wangnc> pg myfile.txt May Day May Day May Day Going Down May Day wangnc> uniq myfile.txt > myfile.txt.1 wangnc> pg myfile.txt.1 May Day Going Down May Day wangnc> sort -u myfile.txt > myfile.txt.2 wangnc> pg myfile.txt.2 Going Down May Day wangnc> 使用-c选项显示行数,即每个重复行数目: uniq -c myfile.txt 使用-d显示重复出现的不唯一行: uniq -d myfile.txt 使用-n只测试一行一部分的唯一性。例如-5意即测试第5域后各域唯一性。域从1开始记数。 如果忽略第1域,只测试第2域唯一性,使用-n2。

 

crypt



gpg - GNU privacy guard



base64



md5sum



sha1sum
crypt



gpg - GNU privacy guard



base64



md5sum



sha1sum
wall - send message to all terminal users



$ cat MESSAGE | wall



$ wall < MESSAGE

 

管道|(pipe)与文件重定向区别

1、管道命令只处理前一个命令正确输出,不处理错误输出

2、管道命令右边命令,必须能够接收标准输入流命令才行。

接收标准输入的命令才可以用作管道右边。否则传递过程中数据会抛弃。 常用来作为接收数据管道命令有:sed,awk,cut,head,top,less,more,wc,join,sort,split 等等,都是些文本处理命令。
1801.关于 nohup 后台运行的问题:

    nohup就是拒绝hup信号,没什么其他用途,

    如果是shopt -s huponexit的话,shell在退出的时候自己把自己所有的子进程都发一个hup信号,

    然后就退出了,但是我还没见过哪种发行版会启用这个参数的。

    后台就直接加个&就行了:sh 1.sh & ,退出终端并不会终端程序,sleep 9999 &,然后退出,然后再登录,看下是不是还在 除非你shopt -s huponexit 才会断掉,默认是不会有这个的 ,其实可以直接在脚本内部trap hup信号,这样和nohup就一样了 shopt |grep hup看下,如果是off,就不用nohup 用ping测试了不行,ping是需要tty的,ping自己会判断,如果失去tty就退出 1802.sort的默认分隔符:blank sort默认就是[ \t]:By default a blank is a space or a tab,blank是空白符,不是空格符,空格是space 1803.lastb : 登录不成功用户记录 1804.lsof监控进程或者程序 lsof -i:22 //知道22端口现在运行什么程序 lsof -c abc //显示abc进程现在打开的文件 lsof -p 12 //看进程号为12的进程打开了哪些文件 1805.设置 chattr 让root无法修改:chattr +i file,lsattr file //查看文件属性 1806.mkfs -t vfat /dev/hda6 :将移动硬盘里面的一个分区格式化成vfat格式 1807.mount /dev/cdrom /media/cdrom //挂载cdrom 1808.getent group 532 //通过组ID,来查找组信息 1809.linux的备份还原: dump -S /dev/sda2 //查看一下要备份/dev/sda2所要的容量 dump -0j -f /dev/hda2/sda2_bak.dump.bz2 /dev/sda2 //将sda2进行备份并压缩 restore -t -f /dev/hda2/sda2_bak.dump //查看备份信息 restore -r -f /dev/hda2/sda2_bak.dump //还原备份 1810.linux添加、删除网段路由: route del -net 172.168.0.0 netmask 255.255.0.0 dev eth0 //删除 172.168这个网段 1811.nmap安全扫描: nmap -sP 172.30.4.0/24 //在这个网段内有多少用户在我的主机上操作,一个不错的安全检查工具 1812./sbin/killall5 杀死除了内核线程和自己的session(当前shell)之外的所有进程(root会把当前shell也杀了),sysvinit-utils里面带的 1813.perl正则:环视 不匹配多个字符 (?<=) (?=) # 每组环视都成对出现,分为前视、后视 (?<!) (?!) 匹配到非行首的2013的正则: echo "20130331_ershouch_putong_post_phoneQuit 120130401_ershouch"|grep -P '(?<!^)2013' # 绕一点的写法:grep -P '(?!^2013)2013' 1814.文件名乱码后,file -i 查看编码: ls|file -i - /dev/stdin: text/plain; charset=utf-8 1815.linux 如何复制用户信息到另一台机器 1. 复制3个文件:/etc/passwd,/etc/group,/etc/shadow 2. 为各个用户创建home目录 3.复制用户home目录下的.bashrc .bash_profile 1816.从世界标准时间中心获取时间: ntpdate 0.pool.ntp.org 1817.alias只是在交互式shell下才有生效,因为其他环境不会执行profile和rc 1818.关于cp覆盖一个正在运行的文件,遇到:cp: cannot create regular file `test': Text file busy 其实这是新版本linux的一个特性,老版本没这个问题,而且二进制文件没问题,文本文件有问题 当时一个脚本,换到debian7上怎么都不行,发现是flock的问题,新版本的flock,如果你flock一个脚本, 那么这个脚本就没法执行了,二进制文件没事。 我去官网找源码编译了下,果然是这样,应该在某个版本的时候改了策略 1819.control + c 发送 SIGINT 信号的问题: 如果你用kill指令而不带任何参数,实际上是发送了一个SIGKILL信号。但是kill指令是可以发送指定信号的, 比如你要发一个SIGINT信号,可以这样:kill -s SIGINT process_name 1820.awk -F 域分隔符转义问题: echo 1[ab]2[ab]3[ab]4|awk -F'\\[ab]' '{print $2}' #注意单引号、斜杠问题,其实完整的后一个也要转义的。 1821.convmv 转换文件名编码,其实这是一个 perl 脚本: 11:19:40#tp#test> echo 中国|iconv -f utf-8 -t gbk|xargs touch 11:19:47#tp#test> ls ?й? 11:21:32#tp#test> convmv -f gbk -t utf-8 * --notest Your Perl version has fleas #37757 #49830 1822.tail -f 和 grep 进行日志的实时监控:# 其实tail -f用的就是inotify tail -fn0 /var/log/php.log|grep --line-buffered error|while read line do echo $line|mail -s error [email protected] done 1823.大量time-wait:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' #vi /etc/sysctl.conf net.ipv4.tcp_tw_reuse = 1 #将TIME-WAIT sockets重用 net.ipv4.tcp_tw_recycle = 1 #开启TCP连接中TIME-WAIT sockets的快速回收 # 注意 tcp_timestamps, tcp_tw_resycle 不要同时开启 # http://blog.sina.com.cn/s/blog_781b0c850100znjd.html # http://www.litrin.net/2013/03/01/android%E4%B9%8B%E7%BD%91%E7%BB%9C%E4%B8%A2%E5%8C%85%E4%BA%8B%E4%BB%B6/ #sysctl -p 1824.使用 LC_ALL=C 的意义: Linux中有关locale的设置会影响大量的命令行工具,其中包括排序工具。 多数安装的Linux系统都将LANG或者其他的locale默认设置成US English。 但这可能会导致排序及其他命令慢上好几倍。 因此export LC_ALL=C 能避免使用i18n形式处理数据,带来性能提升。 1825.了解sort的常用选项 (-t,-k, -s)如何工作: 注意-k1,1只会排序第一列,而-k1会根据整个行排序。 -s能实现稳定排序。 例如,先使用第二个域排序,再按照域一排序,可以用这段命令实现 cat INPUT_FILE | sort -k1,1 | sort -s -k2,2 echo "\ 2 1 1 1"|sort -sk2,2 这个只是在 col2 有相同值的时候,保持其它列的顺序维持不变 1826.需要输入制表符,可以使用 Ctrl-V <tab> 或者 Ctrl-V-I 或者 $'t' 1827.kill -3 <pid>:SIGQUIT 在调试Java程序时,使用此命令,可以在stderr/logs中找到完整的stack trace,堆信息(包含垃圾收集的细节). 1828.curl 设置超时时间,并获取返回码: curl -m9 g.cn/a.gif -so a.gif -w '%{http_code}\n' 1829.curl FTP 下载文件: curl -T "{file1,file2}" http://www.uploadtothissite.com 或者这个也是支持的,man curl里面有 -X PUT 就是 -T ,--ftp-method 指定ftp方式,比如get还是put 1830.ls -A和-a的区别是-A不显示.和.. 1831.一些配置文件的路径区别: profile是login shell,rc是non-login shell,etc下面是共用的,自己目录下面是用户自己的。 1832.通过 secure CRT 的 sftp 协议上传下载文件: 与远程LINUX服务器交换数据。一般情况下通过以下几种。 1、是通过NFS通过MOUNT来挂接远程WINDOWS共享的网络文件系统CFIS进行数据交换。 2、通过HTTP单方面交换数据。 3、通过FTP来交换数据。 4、通过SFTP使用SSH交换数据,这个功能利用了Secure CRT和SSH的功能来实现,非常简单也需要中转服务器。 sftp> lcd C:/Users/june/Desktop sftp> lpwd C:/Users/june/Desktop sftp> get part-r-00000 1833.在linux下如何将中文目录压缩成中文压缩包 rar和7z可以保存编码,其他都不行,zip、tar打包的要在同一操作系统解压,否则是乱码。 unix用tar打包的文件,在windows下解压是乱码,因为当时unix下是utf-8的,然后windows下是gbk的, 所以如果你把U盘拿回linux上,用utf-8挂载,又是中文了。 要看挂载的时候的编码,如果都是gbk的话,是一样的。现在对于fat和nfts,默认就是用gbk编码挂载的 当然,windows是没法选择挂载的时候的字符编码的,文件编码和挂载的时候的编码没关系的 linux 可以选择挂载编码:mount后面有参数的,iocharset 1834.rsync 的 --exclude 排除文件/文件夹用法: --exclude=/dir 只排除 /dir --exclude=dir 排除/dir abc/dir a/dir /data/dir /data/abc/dir 如果你用--exclude=dir,那么上面两个都被排除了, 其实相对路径就是通配所有的路径,绝对路径只排除一个 --exclude-from=FILE是你要exclude的所有东西都写在FILE这个文件里面,每个一行 10:35:22#tp#test> find . ./d ./s ./s/a ./s/b ./s/b/a 10:35:46#tp#test> rsync -nav --exclude=a s/ d/ sending incremental file list ./ b/ 10:35:59#tp#test> rsync -nav --exclude=/a s/ d/ sending incremental file list ./ b/ b/a/ 1835.关于 awk 的 block 缓存问题: iostat 1|awk '{print $1;fflush()}' >a grep也有,--line-buffered可以按行来缓冲,而不是按block来缓冲, 这样可以马上看到结果,但是数据量大的时候性能会很差,例如: while sleep .5;do echo $((i++));done|grep .|cat 1836.在指定时间执行 top 批处理模式获取系统状态信息: at -f <(TERM=linux top -b -n 1 >/tmp/top-report.txt) now+1minutes top -p 4360,4358 # 监控指定进程 top -U johndoe # ‘U’为 真实/有效/保存/文件系统用户名。 top -u 500 # ‘u’为有效用户标识 Top 遍历 /proc 文件夹,以收集进程信息:strace -o /tmp/trace.txt top -b -n 1 1837.在当前文件夹下启动一个内置的 php webServer,类似 python -mSimpleHTTPServer,PHP 5.4.0+ php -S 127.0.0.1 8080 -t /dir 1838.杀死登录用户的所有进程: pkill -u abc # -t pts/n 终端 -u 是effective user ID,-U 是real user ID pkill python -t pts/1 注意 pkill 一般要加 -x,否则它会模糊匹配,比如 pkill mysql,它会把 mysqld 也干掉了。 1839.sed c\ 命令替换问题: sed '/AA/{c\CC}' example.txt # sed: -e 表达式 #1, 字符 0: 未匹配的“{” 解决方法有2个: 1.分成两行写:c\换行CC换行} 2.使用-e参数:sed -e '/AA/{c\CC' -e '}' 如果你把它写成一行,c命令会把后面的内容都当成要替换的内容,包括大括号,所以会报错。 1840.linux下ps -fe和ps aux都是截断,除非加-w, 我屏幕宽度157个字符,就是157截断,除非-ww,这样才是完整的 13:19:50#tp#~> echo $COLUMNS 157 13:19:53#tp#~> ps -fe|wc -L 157 13:19:58#tp#~> ps -few|wc -L 157 13:20:00#tp#~> ps -feww|wc -L 768 13:20:02#tp#~> 1841.readlink 获取脚本当前的绝对执行路径: readlink /proc/7686/fd/255 1842.uniq 去重跳过 n 个字符/字段的用法: echo "hi Linux hi LinuxU hi LinuxUnix hi Unix"|uniq -c -w 8 # -w 只比较前 n 个字符 3 hi Linux 1 hi Unix echo "aabb xxbb bbc bbd"|uniq -D -s 2 # -s 不比较前 n 个字符 aabb xxbb echo "hi hello Linux hi friend Linux hi hello LinuxUnix"|uniq -D -f 2 # -f 不比较前 n 个字段,-d 打印重复行一次,-D 打印所有重复行 hi hello Linux hi friend Linux 1843.bash解析命令行参数,一般用 getopt 或者 getopts,getopts内置,但是不支持长参数 1844.关于 ps -ef|grep [s]sh 可以排除自身的解释: 1、管道是异步执行的:在执行ps的时候, grep也已经被执行, 不存在ps先执行后再把结果管道给grep的说法. 因此 ps -ef|grep ssh 可能会有两条/一条结果(ssh进程存在的情况下) 2、其次在PS的结果中, grep行是 [s]sh, 而grep过滤的内容是ssh, 所以就不会命中grep自己. 1845.rsync 的几个同步问题: 最好别加 -u :否则如果回滚的话,不会同步,比如今天发了一个文件,结果有问题,回滚到昨天,用rsync,他不会更新远程的文件 因为那个文件没目的地的新,所以因为-u参数,跳过,不会同步 rsync 比较文件,决定需要传输,默认采用 quick check 模式(size+timestamp),而不是 checksum,这样省 IO timestamp 可以通过 --modify-window 修改,防止两端的时间差带来的影响 -I, --ignore-times,是关闭 quick check 条件,每次全量同步,而不是增量同步,这样 rsync 没有优势,不如 scp,可以省掉 服务端 IO --size-only、-c, --checksum 都是修改 quick check 条件,前者仅检查大小,后者用 MD5 校验和判断文件是否变化 可以服务端禁掉一些浪费 IO 的选项:/usr/share/doc/rsync/examples/rsyncd.conf refuse options = checksum dry-run # debian的rsync默认配置 1846.nc 的妙用: nc 远程传输文件: nc -lp 1235 <a.log # centos的话要注意,用-l,不是-lp,然后和redhat、debian、官方,参数都不一样 nc 1.1.1.1 1235 >a.log nc -l -p 3003 -e /bin/bash nc 中一行 Bash 脚本创建并启动 Web Server:# 不过还是 pythom -m SimpleHTTPServer 好用 while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; cat index.html; } | nc -l 8080; done netcat可以一行模拟远程bash服务: netcat -lp 8888 -e /bin/bash 1847.wget 全站下载/抓取: wget -mp -nv 可以模拟一部分,不过css和js里面调用的不行。 还有域名白名单用-D指定 ,否则只抓当前域名的 curl -sLO http://product.yesky.com/mobilephone/list[1-347].html 加个-L,list1的时候有跳转 1848.read 读入两个变量: echo "a b"|(read x y;echo $x;echo $y) # read x y <<<"a b" 1849.ps 找出命令的启动时间: ps -eo pid,lstart,cmd 1850.利用 kill 处理 cpu 温度过高的进程: 面对 cpu 负载过高导致温度过高的情况,直接把top里面cpu使用率最高的kill -19,然后再 kill -18 回来 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 18是继续,后面两个都是暂停,其实CTRL-Z就是19或者20信号,具体可以自己trap以下,CTRL+C是2信号 19 和 20 的差异,请见 man 7 signal 1851.date 里面时间的 + - 注意格式会影响结果/时区(最安全的写法是不要带符号,用自然语言即可): date -d'2013-07-01 09:52:33 +1 minutes' # 这个+1被当成时区了 Mon, Jul 01, 2013 4:53:33 PM date -d'2013-07-01 09:52:33 1 minutes' # 同样 -1 也会有问题 Mon, Jul 01, 2013 9:53:33 AM date -u --date='+2 minutes 13-07-01 09:52:33' # 把 + - 时间放在最前面也行 Mon Jul 1 09:54:33 UTC 2013 date -u --date='13-07-01 09:52:33 +0 +2 minutes' # 注意前面的 -u UTC时间,少了也会有问题 Mon Jul 1 09:54:33 UTC 2013 date -u --date='13-07-01 09:52:33 GMT +2 minutes' # 指定时区 Mon Jul 1 09:54:33 UTC 2013 1852.gsub 去除单引号分割字符串: echo "1,2,3,'e,f,g','a,b,c',2,"|awk -F"'" '{for(i=1;i<=NF;i+=2)gsub(","," ",$i)}1' 1853.shell 编码规范:注意 [[ "x"$var == "x" ]], "x" 要放在前面,防止 -x 的出现 1854.巧用行号实现行内去重: echo "a b c a b c b"|awk '{for(i=1;i<=NF;i++){if(last[$i]!=NR)a[$i]++;last[$i]=NR}}END{for(i in a)print i,a[i]}' 1855.流量监控的话我觉得还是用iptables好,每天 iptables -vL 记录流量,然后 iptables -Z 清空 把端口和ip写在iptables的acl里面就, 可以按端口和ip监控,还可以指定协议或者连接状态 1856.平滑的切分 nginx 日志: mv tracklog.ooxx.com.access.log ${log_date_dir}/tracklog.ooxx.com.access.log.${log_name_date} kill -USR1 `cat /var/run/nginx.pid` mv xx.log date.xx.log,nginx会去写date.xx.log,你reload,就写xx.log了,fd没释放,进程会占用这个文件继续写 如果 mv 后没有 reload 就会有问题 user1 reopen,这个信号应该是nginx自己的,他的程序里边应该会捕获这个信号 reload 是把子进程重启了 1857.tree -d 打印目录: tree -d|awk '{if(/-- 2013/){if(f==0)print;f=1}else{f=0;print}}' 1858.top -p 监视单个进程: top -p $(pgrep -d, nginx) 1859.tail -F 根据文件名而不是文件描述符 FD 来监视文件: 比如 vim 编辑文件 FD/inode 会变化:vim 默认类似 sed 不是 inplace,lsof|grep test.txt 可以看到源文件被 deleted 了 此时 tail -f 追踪不到变化了,当然如果你 vim 中 se nowb(writebackup)的话不会改变 inode,vi -u NONE -N 也不会 1860.关于 .bashrc 环境变量在非登陆shell(nologin)环境下无法使用的问题: crontab 那种非登陆shell用不了 .bashrc 里的设置,需要 export,然后 source 让环境变量重新加载。 .profile 也一样 1861.正反进程替换的用法: iconv -f utf-8 -t gbk < <(echo 中国) > >(xxd) 上面这个和 echo 中国|iconv -f utf-8 -t gbk|xxd一样的 其实 <() 、<() 都是管道,<() 用在比如这个命令里面的变量你后面还要用到的时候 1862.sort 排序字符串中的数字: echo "aa2 aa1 aa13 aa12"|sort -k1.3 -n -k1.3 相当于 -k1.3 -k1.9 排序指定字段中的指定范围的字符串,如果是文件名的话,还可以 ls -v 按版本号排序 1863.sort -m 中的归并排序 MergeSort,注意归并排序需要你参与归并的文件先有序: 21:15:44#tp#~> seq 1 2 999999 >b 21:15:49#tp#~> seq 0 2 999999 >a 21:15:52#tp#~> time sort -m a b >/dev/null real 0m0.287s user 0m0.268s sys 0m0.016s 21:15:55#tp#~> time cat a b|sort >/dev/null real 0m3.873s user 0m3.824s sys 0m0.040s 21:16:05#tp#~> 1864.du -b:-b是用字节数,然后显示真实使用了多少,而不是占用了多少。试着比较 du -B1 1865.关闭 centos 的 ipv6 功能: vi /etc/sysconfig/network 添加 NETWORKING_IPV6=no IPV6INIT=no vi /etc/modprobe.conf 添加 alias net-pf-10 off alias ipv6 off 1866.关闭 centos 的 iptables 防火墙: /etc/init.d/iptables status /etc/init.d/iptables stop 永久关闭: chkconfig --level 35 iptables off 或者 直接 iptables -F 删掉所有规则 也可以直接修改 /etc/sysconfig/iptables 添加一条 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT #/sbin/iptables -I INPUT -p tcp –dport 80 -j ACCEPT #/sbin/iptables -I INPUT -p tcp –dport 22 -j ACCEPT #/etc/rc.d/init.d/iptables save 1867.curl 获取 request、response 请求头信息: curl -svo /dev/null http://www.hao123.com/ # curl -I 获取的是响应头信息 1868.bash 获取当前正在执行脚本的绝对路径: echo "scriptPath1: "$(cd `dirname $0`; pwd) echo "scriptPath2: "$(dirname $(readlink -f $0)) 1869.进程代换的本质: 其实进程替换相当于用fd来替代一个文件 11:23:11#tp#~> echo <(pwd) /dev/fd/63 11:26:37#tp#~> pwd执行结果在/dev/fd/63里面,然后你可以用cat /dev/fd/63这样的方式实现和cat a一样的操作。 1870.date 获取指定日期对应一年中的周序号和一周中的日序号 man date | grep '%[UVWw]' %G year of ISO week number (see %V); normally useful only with %V %U week number of year, with Sunday as first day of week (00..53) %V ISO week number, with Monday as first day of week (01..53) %w day of week (0..6); 0 is Sunday %W week number of year, with Monday as first day of week (00..53) seq 1 10 | xargs -i date -d "2012-1-{} 0:0:1" +"%V,%U,%W,%w" 1871.巧用 shell/awk 解决算术题: 学习 X 学 == 好好好 seq 10 99 | awk '{print $1, $1*substr($1,1,1)}' | grep -P ' (\d)\1\1' 1872.find 命令顺序与逻辑关系带来的高危操作: find . -delete -name *.pyc -delete 和 后面的 -name 是 and 的关系,而且最好 *.pyc 带上双引号,防止shell扩展后带来的空格问题 1873.kill -9 kill -9 1 会重启 一般-9杀不掉就两种,一个进程状态是D,磁盘io卡住了,一个是Z,已经是僵尸了,没法死了。 其实僵尸只是死亡的一个中间过程,每个进程结束的时候都会经历,不过一般很快,你根本看不到。 1874.linux 下查看线程运行在哪个 CPU 上: ps -eo ruser,pid,ppid,lwp,psr,args -L|grep mysql-proxy 查看线程: ps -eLf|grep mysql-proxy # ps axms,ps aux,pstree -p pid,top -Hp pid,cat /proc/pid/status 其中: LWP -- 轻量级进程,即线程,这里显示的是 thread id。 NLWP -- 线程数,即 number of threads in process。 1875.time 时间含义: real:代表实际花费的时间 user::代表cpu花费在内核外的时间 sys:代表cpu花费在内核以内的时间 通过把sys和user时间加起来可以获得cpu在你的程序上花费的时间。 如果sys和user加起来的时间比real时间要小很多,那么你可以猜想你的程序的大部分性能瓶颈应该是IO等待的问题。 Note that this is across all CPUs, so if the process has multiple threads it could potentially exceed the wall clock time reported by Real. 所以多核多线程有可能 real < user + sys 1876.LC_ALL=C 的含义: Linux中有关locale的设置会影响大量的命令行工具,其中包括排序工具。 多数安装的Linux系统都将LANG或者其他的locale默认设置成US English。 但这可能会导致排序及其他命令慢上好几倍。 因此export LCALL=C能避免使用i18n形式处理数据,带来性能提升。 1877.关于 test -n:[ -n ] 的问题: -n要带参数才是选项,否则相当于 [ "-n" ], 加了双引号就是 [ -n "" ]这个时候-n是参数了 igi@macbook:~ $ [ ] && echo 'yes' igi@macbook:~ $ [ xxx ] && echo 'yes' yes 1878.关于 2>&1 和 2&>1 的含义: 2>&1和2&>1都可以的,就是格式,其实&没意义,不一定在>后面。 其实最好还是写&>,因为有&>>这种写法,但是>>&是不对的。 >&和&>是一个组合,&不是和1或者2组合在一起的,2 >& 1 如果你携程2 > &1会报错的,2后面的空格去掉。 1879.printf 与 awk/sed 位数补全、千分位分割符: printf "%18s\n" `echo 123456789.12 | sed '{:a;s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta}'` echo '123456789.12'|awk '{printf "%'"'"'18.2f\n",$0}' # "%\04718.2f\n",printf 格式定义是:%'18.2f echo '123456789.12'|xargs -I@ printf "%'18.2f\n" @ # 其实 awk 调用的 printf 和 shell 下的用法一样 更多用法请参见:http://hi.baidu.com/leejun_2005/item/9d91b7fe9c628259c8f3376d 1880.利用死循环进行 ssh -D 链路中断自动重连: 链路可能会断,我直接 while :;do ssh -Dport ip;done 就好了,加了-f的话我还得去判断链路是否断了,麻烦 ssh 远端会 block 住,while 不会退出,等链接断了才重新循环,否则用了-f的话我还要while sleep 1;do ps -fe|grep ssh去判断 1881.shell 下的文件锁: 14:47:30#tp#~> flock abc sleep 9999 & [1] 16231 14:47:40#tp#~> flock abc echo abc ^C #这里因为上一条语句锁了abc文件,所以需要等待上面语句执行完成,释放锁,才能执行echo命令 14:47:45#tp#~> flock def echo abc abc #换个文件就可以执行 14:47:50#tp#~> 1882.禁用使用 root 账号,用 sudo 控制权限 Cmnd_Alias NP = /bin/netstat,/usr/bin/lsof,/home/bin/lsof.sh,/usr/bin/atop walkerxk ALL=(ALL) PASSWD:ALL,NOPASSWD:NP 这些命令/脚本不用密码,其他要密码 1883.tc(TrafficControl) 限制网络速度,模拟网络延时: 限制 100ms 的网络延时,其中 lo 是网卡的名称, 本地调试: sudo tc qdisc add dev lo root netem delay 100ms sudo tc qdisc del dev lo root netem delay 100ms http://stackoverflow.com/questions/614795/simulate-delayed-and-dropped-packets-on-linux/615757#615757 也可以 iptables: iptables -A INPUT -m statistic --mode random --probability 0.01 -j DROP Be careful, anything above about 0.14 and most of you tcp connections will most likely stall completely. 1884.正在运行的程序转到后台运行: 对于长时间运行的程序可以使用 screen、nohup、setsid 来避免被中断, 如果对于已经运行,但是开始忘记使用screen、nohup、setsid的程序,可以使用disown命令,真是犀利的小工具, 使用方法:ctrl+z,jobs,bg %jobid,disown -h %jobid。 如果ctrl+z 无效,可以用 kill -20 $pid 1885.杀不掉的僵尸(zombie)进程: Linux的进程,有以下几种状态: D Uninterruptible sleep (usually IO) R Running or runnable (on run queue) S Interruptible sleep (waiting for an event to complete) T Stopped, either by a job control signal or because it is being traced. W Paging (not valid since the 2.6.xx kernel) X Dead (should never be seen) Z Defunct ("zombie") process, terminated but not reaped by its parent. 当一个进程处于Z状态,我们称之为zombie进程,正常情况下,处于zombie状态的进程,会很快地被它的父进程回收, 以致于我们根本不会注意到zombie进程的存在。可在实践过程中,却有一些无法使用kill -9命令杀掉的zombie进程, 如果某个进程一直处于zombie状态,可能会带来一些严重的问题,例如,假设这个进程没有正确地close掉socket, 就会导致这些socket处于close_wait状态,这些socket将会占用系统的ip/port资源,将导致其他程序无法创建特定socket。 当出现「杀不掉」的zombie进程,我们常常归咎于kernel的bug,不了了之,但其实还有一种情况常常被忽略。 让我们看看上面的这个zombie进程内部,是否还有其他线程(使用top命令的-H参数): top -b -H -p pid 如果有线程处于D(Uninterruptible sleep)状态,然而D状态的进程(在Linux中,线程只是特殊的进程)无法被中断, 因此kill -9无法杀掉D状态的进程。也正因为这些D状态的进程的存在,导致父进程无法顺利的回收它们。 我们还需要分析处于D状态的进程卡在了哪里。可通过/proc文件系统查看D状态进程的调用栈: #cat /proc/56337/stack [<ffffffff811b372e>] __blockdev_direct_IO_newtrunc+0x6fe/0xb90 [<ffffffff811b3c1e>] __blockdev_direct_IO+0x5e/0xd0 [<ffffffff811b1317>] blkdev_direct_IO+0x57/0x60 [<ffffffff81113543>] generic_file_aio_read+0x793/0x870 [<ffffffff81177c3a>] do_sync_read+0xfa/0x140 [<ffffffff81178635>] vfs_read+0xb5/0x1a0 [<ffffffff81178962>] sys_pread64+0x82/0xa0 [<ffffffff8100b0f2>] system_call_fastpath+0x16/0x1b [<ffffffffffffffff>] 0xffffffffffffffff 由上图可见,该进程卡在了磁盘的read操作中,很可能是磁盘坏了。 1886.bash 命令路径的 hash 缓存:真实的文件已经卸载,但是命令执行路径还是老的路径: 如果某个命令被缓存,可以:command -V、type、hash -t 看出来 hash -l 命令可以查看当前所有缓存的命令路径 可通过如下命令之一清除缓存: hash -r hash -d python2.7 1887.find 的一些用法: (1)相反匹配:find -maxdepth 1 -not -iname "MyCProgram.c" (2)使用inode编号查找文件:find -inum 16187430 -exec mv {} new-test-file-name \; 当文件名中含有特殊字符或者乱码时,可以考虑 inode 方式删除:ls -i1;find -inum 804180 -exec rm {} \; (3)根据文件权限查找文件:find . -perm -g=r -type f -exec ls -l {} \; 使用八进制权限形式:find . -perm 040 -type f -exec ls -l {} \; (4)当前目录下的非隐藏空文件:find . -maxdepth 1 -empty -not -name ".*" (5)find -newer、-size 1888.printf 生成从 a 到 z 的字母表,字母之间不包含空格 printf "%c" {a..z};printf "%c" {a..z} $'\n' 如果想要快速地将 printf 的结果保存到变量中,可以使用-v选项: printf -v varStr "%c" {a..z} 1889.利用变量扩展重复输出 10 次字符串 echo foo{,,,,,,,,,,} 1890.利用 fold 限制每行多少字符: fold -w10 urfile |xargs -n6 |awk '{print (NR-1)*60+1,$0}' 1891.sort 使用 tab 键作为分隔符,出现“sort: multi-character tab”错误: 因为 sort -t 是不支持多个字符做分隔符的,你可以用另一种方式转义: -t$'\t' # $'\t'是单个字符 当然了,你也可以使用 Ctrl+v+TAB/I # 先按 ctrl-v,再按 tab,这个组合和其它组合不一样 1892.telnet 日志重定向的问题: 直接 telnet ip port <<EOF 会立即被 close 掉,nc 也不行, 因为 telnet 的执行是非阻塞的,执行完了就退出 不管中间的过程,和 ssh 不一样 { sleep 3; echo cmd; sleep 30; } |telnet 第一个 sleep 防止 telnet 因为网络原因导致登录还未成功就执行后面的命令,进而导致整个失败 第二个相当于你的超时时间,超过30s 这次telnet会话就断掉,后面的sleep 其实是为了给日志回传一些时间 1893.注意 sort 按字段排序对后续字段的影响: sort -k1,1d -k2n 20131023.txt|head # 注意sort -k1,1d 按字典序(默认)后断开,然后 -k2n 按数字排序,否则 sort -k1 -k2n 会全局按字典排序 1894.su 与 sudo 的作用区别: su 用来切换用户帐号 sudo 是用其他用户的权限来运行程序,而无需知道那个帐号的密码,这是在 sudoers 文件里配置的,如果给ALL就相当于root了。 1895.awk 中正则不区分大小写:IGNORECASE 如果 IGNORECASE 非零,那么 正则、FS、RS、RE ~、!~、gensub()、gsub()、index()、match()、split()、sub() 以及所有 built-in functions 在正则操作时都将忽略大小写 注意:数组下标不受此影响,但是 asort() 和 asorti() 是受影响的。 例如 /aB/ matches all of the strings "ab", "aB", "Ab", and "AB" 1896.read -r 不转义反斜杠:遇到 \ 作普通字符解释 1897.crontab 编辑文件的路径: crontab -u userName -e #编辑指定用户的文件 crontab -e #其实编辑的是 /var/spool/cron 下面对应 username 的文件 crontab #操作、调度日志放在 /var/log/cron 1898.parallel 利用多核CPU来加速你的Linux命令: 它让我们所有的CPU内核在单机内做神奇的map-reduce操作,当然, 这还要借助很少用到的–pipes 参数(也叫做–spreadstdin)。这样,你的负载就会平均分配到各CPU上。 当然,这只对 CPU 密集型的计算有效,对 IO 密集型瓶颈在磁盘了。 cat rands20M.txt | parallel --pipe awk \'{s+=\$1} END {print s}\' | awk '{s+=$1} END {print s}' cat bigfile.txt | parallel --block 10M --pipe grep 'pattern' # –block 10M参数,这是说每个内核处理1千万行 cat bigfile.bin | parallel --pipe --recend '' -k bzip2 --best > compressedfile.bz2 1899.查看 linux 系统安装时间: ls -lct --full-time /etc/ | tail -1 | awk '{print $6, $7, $8}' 1900.kill 让命令暂停与重新运行: #暂停指定的进程 pid=`ps -ef|grep exp|grep -v grep|awk '{print $2}' ` kill -19 "$pid" #等待2小时 sleep 7200 #运行被暂停的进程 kill -18 "$pid" 注意: 19) SIGTSTP、18) SIGCONT 每个系统kill含义不一样,具体 kill -l

 

你可能感兴趣的:(shell)