
shellpasswd 文件:多行多列的表格列的分隔符是冒号root:x:0:0:root:/root:/bin/bash第一列是用户名:root第二列是密码但是通过加密放到了shadow中第三列是用户id第四列是组id第五列是用户描述第六列是home目录地址第七列是用户登录之后执行的第一条命令确定用户当前用什么shell1.echo $SHELL 2.看 passwd 文件用户的启动命令shell内建命令比如 cd、alias、umask 在which xxx中找不到就是内建命令这不是一个进程只是调用了shell进程的函数shell脚本shell脚本相当于把一行行命令集中一次性处理在执行命令的过程中会fork一个子进程并调用exec执行./test.sh这个程序exec系统调用把子进程的代码段替换成./test.sh程序的代码段并从他的_start开始执行但是./test.sh只是个文本文件根本没用代码段和——start函数怎么解决呢实际上exec还有另外一种机制如果要执行的是一个文本文件并且第一行用Shebang指定了解释器则用解释器程序的代码段替换当前进程并且从解释器的_start开始执行而这个文本文件被当作命令行参数传给解释器。eg:#!bin/bash # 指定用的解释器echoHelloworldcd..ls执行脚本的几种方式:可以用 ./test.sh执行 也可以用 source 脚本地址**这种方式执行脚本不会产生一个子进程而是将脚本的命令都加载进来执行** 还可以用 . 脚本地址跟 source 一样shell 基本语法变量变量的定义VARBNAMEvalue变量的使用用$符号跟上变量名表示对某个变量进行取值变量名可以加上花括号来表示变量名的范围echo$VARBNAMEecho${VARBNAME}VARBNAMEvalue注意:等号两边都不能有空格变量的分类* shell 内变量 (这个变量只存于shell内) 全局变量 (shell中不使用任何修饰符修饰的变量都是全局变量) 局部变量 (用 local 来修饰) shell内变量只能在当前shell进程中使用跨进程不允许使用多个子进程 * 环境变量 操作系统自带每个进程都会有 当启动一个子进程时环境变量是从父进程拷贝到子进程全局变量以及局部变量eg#!/bin/bashglobalhellofunctiontest(){global2worldlocalLocalValuecastecho$LocalValue}testecho$global$global2echo$LocalValue#这里local是局部变量在函数结束的时候就已经全部释放了自然看不到输出结果环境变量egexportvarnamevalue删除变量用unset命令可以删除已定义的环境变量或本地变量 不管是环境变量还是普通的shell变量都可以使用unset删除unsetVARNAME文件名代换用于匹配的字符统称为通配符* 匹配0个或多个任意字符 ? 匹配一个任意字符[若干字符]匹配方括号中的任意一个字符的一次出现代换文件的前提:文件必须存在如果不存在是代换不了的命令代换shell先执行该命令然后将输出结果立刻代换到当前命令行中eg#!/bin/bashDataTimedate# 由这个符号也是一条命令相当于先把这个命令保存再输出与 $(date)的功能一样echoDateTime is $DataTime算数代换使用$(())用于算术计算(())中的Shell变量取值将转换成整数跟$[]等价注意:$(())中只能用加减乘除和()运算并且只能做整数运算eg:#!/bin/bashVAR45echo$((VAR3))使用$[base#n]做进制计算其中base表示进制,n按照base进制解释后面再有运算数按十进制解释eg:#!/bin/bashecho$[8#1011]shell引号Shell脚本中单引号和双引号都是字符串的界定符而不是字符的界定符。单引号用于保持引号内所有字符的字面值即使引号内的\和回车也不例外但是字符串中不能出现单引号单引号eg:echoaaa bbbbaaa bbbb双引号eg:被双引号括住的内容将被视为单一字串它防止通配符扩展但允许变量扩展eg:#!/bin/bashvara becho$var输出的结果就是 a b 中间有空格但是我想 var 是一个整体我并不想把他拆开变量于是就可以用echo $var条件测试条件测试是用来表示真假直接使用某条命令的返回状态(main函数返回值)若 main()函数返回0即为真若main函数返回非0即为假如何获取返回状态通过$?来获取上一条命令的返回状态使用命令test或[可以测试一个条件是否成立! EXPRESSION取反 EXPRESSION is false EXPRESSION1 -a EXPRESSION2 (与) both EXPRESSION1 and EXPRESSION2 are true EXPRESSION1 -o EXPRESSION2 或 either EXPRESSION1 or EXPRESSION2 is true -n STRING 判断字符串不是空串 the length of STRING is nonzero STRING equivalent to -n STRING -z STRING (判断字符串长度为0) the length of STRING is zero STRING1 STRING2 判断字符串相等 the strings are equal STRING1 ! STRING2判断字符串不相等 the strings are not equal INTEGER1 -eq INTEGER2 判断整数相等 INTEGER1 is equal to INTEGER2分支结构if结构结构:if 命令|条件测试 then xxxxx elif 命令2|条件测试 else xxxx fi如果then跟if写在同一行加分号,else后不需要跟theneg:#!/bin/bashif[-f/bin/bash]thenechoBash is installed.elseechoBash is not installed.ficase结构case命令可类比C语言的 switch/case语句,esac表示case语句块的结束Shell的 case 可以匹配字符串和 Wildcard每个匹配分支可以有若干条命令末尾必须以;;结束结构:case表达式inval1|pattern1)xxxxx;;val2|pattern2);;esaceg:#!/bin/bashechoIs it morning or evening? (morning/evening)readtime_of_daycase$time_of_dayinmorning)echoGood morning!;;evening)echoGood evening!;;*)echoInvalid input. Please enter morning or evening.;;esac循环for循环结构:forvarnamein列表dodoneforvarnamein列表;dodoneeg:#!/bin/bashforFinBanana apple pear;doechoI like$Fdone#!/bin/bashsum0forFin{1..100};dosum$((sumF))doneechoThe sum is:$sumwhile 循环结构: 与C类似 while 命令|条件测试 do xxxx doneeg:#!/bin/bashsum0cnt1while[$cnt-le100];dosum$((sumcnt))cnt$((cnt1))doneechoThe sum of numbers from 1 to 100 is:$sum#!/bin/bashechoEnter Password:readpasswordwhile[$password!manager];doechoPlease try againreadpassworddoneechoAccess granted位置参数和特殊变量$0 相当于C语言 main 函数的 argv[0] $1、$2... 这些相当于位置参数类似C语言中的 argv[1]、argv[2]... $ 表示参数列表$1$2...可以用在for循环中in后面 $? 上一条命令的返回状态 $$ 当前进程号eg:#!/bin/bashsum0foriin$;dosum$[$sum$i]doneechoThe sum is$sum注意:位置参数默认就支持10个$还是支持很多个管道 (命令与命令的交互)可以通过|把一个命令的输出传递给另一个命令做输入实际上是将前面进程的标准输出重定向到后边进程的标准输入标准错误输出是不会重定向的eg:#includestdio.h#includectype.hintmain(){intchgetchar();while(ch!EOF){putchar(toupper(ch));chgetchar();}return0;}echoabc|./main衍生:* more命令 将标准输入的内容(超级多)进行缓慢向下查看只支持向下走不支持往回走 * less 命令比 more 更完善支持往回滚支持类似 vim 的操作 * tee 命令 把结果输出到标准输出另一个副本输出到相应文件重定向 (文件与命令的交互)* cmd file 把标准输出重定向到新文件中 * cmd file 追加 * cmd file 21 标准出错也要重定向到1所指向的file里 * cmd file 21 文件描述符2重定向到文件描述符1中 * cmd file1 file2 输入输出分别定向到两边文件中 * cmd fd 把文件描述符fd作为标准输入 * cmd $fd 把文件描述符fd作为标准输出 * cmd - 关闭标准输入函数在Shell中函数定义中没有返回值也没有参数列表结构: func 函数名() { return 1 } 注意:func可以省小括号也可以省但是这两个必须保留一个 小括号里面也不需要填列表参数return 只能返回参数不能返回其他类型eg:#!/bin/bashfoo(){echoThis is a lion.return1}fooecho$?testfunc(){echoaaaaaaaareturn0}vartestfunc# 将反引号内的命令执行并用执行结果替换掉整个反引号部分#var$(testfunc)echo${var}shell调试方法* -n 读一遍脚本中的命令但不执行用于检查脚本中的语法错位 * -v 一边执行脚本一边将执行过的脚本命令打印到标准错误输出 * -x 提供跟踪执行信息将执行每一条命令和结果依次打印出来可以跟在 命令行后bash -x xx.sh也可以在代码前显示#!/bin/bash -x正则表达式结构: 1.以S开头的字符串 ^S匹配 2.以数字结尾的字符串 [0123456789] [0-9] \d [0-9]$ 3.匹配空字符串(没有任何字符) ^$匹配 4.字符串只包含三个数字 ^\d\d\d$ 控制次数 我们有更好的办法写 ^\d{n}$ 表示前面的单元重复n次 5.字符串只有 3-5 个 {m,n} m表示前面单元最小重复次数n表示最大重复 次数 字母表示法[a-zA-Z] PS:**如果中括号中有多个区间区间之间不要留空格或其他分隔符** 所以 ^[a-zA-Z]{3,5}$ 6.匹配不是a-z的任意字符 [^a-z] 若 ^这个符号出现在中括号内第一个表示**区间取反** 7.字符串有0到1个数字或者字母或者下划线 {0,1} 表示重复0-1次, 也可以表示重复0-1次 ^[0-9A-Z_]?$ 8.字符串有1个或多个空白符号 \s 表示有空格出来的字符 包括 \t\n\r... {1,n}表示重复 1-n次,与 这个符号一样 ^\s$ 9.字符串有0个或若干个任意字符 . 代表任意字符除 \n {} 花括号中两个参数置空表示重复次数任意 0-n * 表示前面的单元重复 n 次 (0-n) ^.*$ 总结: ? 0-1 1-n * 0-n 10.匹配0或任意多组ABC比如ABCABCABCABC 在描述多组ABC时可以用 ()来表示多个单元重新组成一个单元 ^(ABC)*$ 11.字符串内要么是ABC要么是123 需要做选择的时候需要写 |选择两边的一个 ^(ABC)$|^(123)$ 12.字符串只有一个点号 因为 .具有特殊含义表示任意字符所以我们需要对其进行转义 ^\.$ 13.匹配十进制3位整数 十进制三位数有:100-999 ^[1-9][0-9]{2}$ 14.匹配十进制 0-999 数字 这种情况需要 一位数、二位数、三位数分类 一位数:^[1-9][0-9]$ 二位数:^[1-9][0-9]$ 三位数:^[0-9][0-9]{2}$ ^[0-9]|[1-9][0-9]{1,2}$shell中的其他命令sort 命令命令从标准输入中读取数据然后按照字符串内容进行排序 -f 忽略字符大小写 -n 比较数值大小 -t 指定分隔符默认是空格或者tab -k 指定分割后进行比较字段 -u 重复行只显示一次 -r 反向排序 -R 打乱顺序cattest.txt|sort与sorttest.txt一样uniq去除重复的行前提是重复的行连续 -c 显示每行重复的次数 -d 仅显示重复的行 -u 仅显示不曾重复的行eg:sorttest.txt|uniq-c1xiao89man161xiaow10man111xiaowen78man902xio30man50sorttest.txt|uniq-dxio30man50sorttest.txt|uniq-uxiao89man16xiaow10man11xiaowen78man90wc命令 word count* -l 统计行数 * -c 统计字节数 * -w 统计单词数wc-ltest.txt5cattest.txt xiaowen78man90xiao89man16xiaow10man11xio30man50xio30man50wc-ctest.txt77wc-wtest.txt20grep (Global Regular Expression Print)grep 命令是一种强大的文本搜索工具能使用正则表达式搜索文本并把匹配的行打印出来使用权限是所有用户格式以及主要参数Usage: grep [OPTION]... PATTERNS [FILE]... Search for PATTERNS in each FILE. Example: grep -i hello world menu.h main.c PATTERNS can contain multiple patterns separated by newlines. Pattern selection and interpretation: -E, --extended-regexp PATTERNS are extended regular expressions -F, --fixed-strings PATTERNS are strings -G, --basic-regexp PATTERNS are basic regular expressions -P, --perl-regexp PATTERNS are Perl regular expressions -e, --regexpPATTERNS use PATTERNS for matching -f, --fileFILE take PATTERNS from FILE -i, --ignore-case ignore case distinctions in patterns and data --no-ignore-case do not ignore case distinctions (default) -w, --word-regexp match only whole words -x, --line-regexp match only whole lines -z, --null-data a data line ends in 0 byte, not newline Miscellaneous: -s, --no-messages suppress error messages -v, --invert-match select non-matching lines -V, --version display version information and exit --help display this help text and exit Output control: -m, --max-countNUM stop after NUM selected lines -b, --byte-offset print the byte offset with output lines -n, --line-number print line number with output lines --line-buffered flush output on every line -H, --with-filename print file name with output lines -h, --no-filename suppress the file name prefix on output --labelLABEL use LABEL as the standard input file name prefix -o, --only-matching show only nonempty parts of lines that match -q, --quiet, --silent suppress all normal output --binary-filesTYPE assume that binary files are TYPE; TYPE is binary, text, or without-match -a, --text equivalent to --binary-filestext -I equivalent to --binary-fileswithout-match -d, --directoriesACTION how to handle directories; ACTION is read, recurse, or skip -D, --devicesACTION how to handle devices, FIFOs and sockets; ACTION is read or skip -r, --recursive like --directoriesrecurse -R, --dereference-recursive likewise, but follow all symlinks --includeGLOB search only files that match GLOB (a file pattern) --excludeGLOB skip files that match GLOB --exclude-fromFILE skip files that match any file pattern from FILE --exclude-dirGLOB skip directories that match GLOB -L, --files-without-match print only names of FILEs with no selected lines -l, --files-with-matches print only names of FILEs with selected lines -c, --count print only a count of selected lines per FILE -T, --initial-tab make tabs line up (if needed) -Z, --null print 0 byte after FILE name Context control: -B, --before-contextNUM print NUM lines of leading context -A, --after-contextNUM print NUM lines of trailing context -C, --contextNUM print NUM lines of output context -NUM same as --contextNUM --group-separatorSEP print SEP on line between matches with context --no-group-separator do not print separator for matches with context --color[WHEN], --colour[WHEN] use markers to highlight the matching strings; WHEN is always, never, or auto -U, --binary do not strip CR characters at EOL (MSDOS/Windows) When FILE is -, read standard input. With no FILE, read . if recursive, - otherwise. With fewer than two FILEs, assume -h. Exit status is 0 if any line is selected, 1 otherwise; if any error occurs and -q is not given, the exit status is 2.pattern 正则表达式主要参数:(pattern - 表示要查找的字符串或正则表达式。)* \ 忽略正则表达式中特殊字符的原有含义 * ^ 匹配正则表达式的开始行 * $ 匹配正则表达式的结束行 * \ 从匹配正则表达式的行开始 * \ 到匹配正则表达式的行结束 * [ ] 单个字符,eg:[A] 即A符合要求 * [ - ] 表示字符范围eg:[A-Z]即A~Z都符合要求eg:在文件 file.txt 中查找字符串 hello并打印匹配的行 grep hello file.txt 在文件夹 dir 中递归查找所有文件中匹配正则表达式 pattern 的行并打印匹配行所在的文件名和行号 grep -r pattern ~/shell/createfind 命令find 用于在指定目录下查找文件和目录可以使用不同的选项来过滤和限制查找的结果结构以及常见的匹配条件:find [路径] [匹配条件] [动作] * -name 按照文件名查找文件 * -perm 按照文件权限来查找文件 * -prune 使用这一选项可以使 find 命令不在当前指定的目录中查找如果同时使用 -depth选项那么-prune 将被 find 命令忽略 * -user 按照文件属主来找文件 * -group 按照文件所属的组来找文件 * -mtime days按修改时间查找支持使用 或 - 表示在指定天数前或后days 是一个整数表示天数。 * -type 查找某一类型的文件 eg:b(块设备文件)、d(目录)、c(字符设备文件)、p(管道文件)、l(符号链接文件)、f(普通文件)、s(socket文件) * -exec 可以作为一个指令执行eg:查找当前目录下名为 file.txt 的文 件find.-namefile.txt 查找当前目录下的txt文件并且打包成为gzipfind.-name*.txt-execgzip{}\;xargs将标准输入的参数整齐拼凑在一行里面 一般是和管道一起使用sed(Stream Editor)sed 在 shell 脚本 和 Makefile 中作为过滤器使用非常普遍也就是把前一个程序的输出引入 sed 的输出经过一系列编辑命令转换位另一种格式输出 还有一种说法就是它利用脚本来处理文本文件结构:sed option /pattern/action file1 file2 ... 解释: sed 选项参数 /pattern/action(其中pattern是正则表达式action是编辑操作) 待处理文件 sed option -f scriptfile file1 file2 解释: sed 选项参数 -f 脚本文件 待处理文件 * -e 用来指定一段脚本编辑命令 * a 新增 a 的后面可以接字串而这些字串会在新的一行出现(目前的下一行) * c 取代 c 的后面可以接字串这些字串可以取代 n1,n2 之间的行 * d 删除因为是删除啊所以 d 后面通常不接任何东东 * i 插入 i 的后面可以接字串而这些字串会在新的一行出现(目前的上一行) * p 打印亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行eg:sedtest10.txt ashfjklsadfsndhlkj ashfjiksdahfkl asdjfio lllll999999999 oiopi90123-------------------------------sed-e4a helloworldtest10.txt# sed -e 4a\helloworld test10.txtashfjklsadfsndhlkj ashfjiksdahfkl asdjfio lllll999999999 helloworld oiopi90123awksed 以行单位处理文件awk 比 sed 强的地方在于不仅能以行为单位还能以列为单位处理文件。**awk缺省的行分隔符是换行缺省的列分隔符是 连续的空格 和 Tab**当然行分隔符和列分隔符都可以自定义结构:awk option script file1 file2 awk option -f scriptfile file1 file2 **和 sed 类似pattern 是正则表达式,actions是匹配成功后一系列操作** 命令行参数传递方式: * /pattern/{actions} * condition/{actions} 关于 awk 脚本我们需要注意两个关键词 BEGIN 和 END。 **BEGIN{ 这里面放的是执行前的语句 }** ** END {这里面放的是处理完所有的行后要执行的语句 }**eg:awk{print $1}test10.txt ProduceA ProduceB ProduceC以C语言的方式理解 awk 命令$275{printf(%s\n%s\t,reorder);}$275{printf(%s\n,$0);}