是一个多行多列的表格,列的分隔符号是冒号
root:x:0:0:root:/root:/bin/bash
用户名:以前是密码,现在x是加密放到shadow:用户id:组id:
用户描述:home目录地址:用户登入之后执行的第一条命令
如果用户启动的第一条命令不是shell的话,那么执行完命令就会退出
mon:/usr/sbin:/usr/sbin/nologin,这个就不能登入。
echo $SHELL 查看环境变量
看passwd文件用户的启动命令
修改当前用户的shell: chsh
man bash-builtins
#!/bin/bash
# 第一行表示解释器,表明使用的sh解释器
echo HelloWorld
cd .. #这里是子shell进程执行,子shell进程工作目录变化,父shell进程不会受影响
ls
执行脚本:
chmod a+x a.sh
./a.sh # 需要可执行权限
sh a.sh # 需要可读权限,不用可执行权限,在一些没办法调整脚本权限的情况下使用,和第一种方法类似
# 有一个弊端:要调用者关注当前脚本使用的解释器
source a.sh
. a.sh
# 上面的两种都是使用内建命令来执行的,不会创建子shell进程。就在当前shell进程执行。
shell变量通常由字母加下划线开头,由任意长度的字母、数组、下划线组成。
赋值一个变量: VARNAME=value
,注意等号两边不能由空格,否则会被shell解释成命令和命令行参数。
变量的使用,用$符号跟上变量名表示对某个变量取值,变量名可以加上花括号表示变量名的范围,echo $VARNAME
, echo ${VARNAME}_suffix
。使用花括号来分离,不至于将VARNAME_suffix当作一个变量。
#!/bin/bash
globalVar1="Hello" # 全局变量
function test() # 在sh解释器中没有function关键字,在bash中有,所以funcuton关键字可以省略掉
{
globalVar2="world" # 全局变量
local localVar1="itcast" # 局部变量
echo ${localVar1} # itcast
}
test
echo ${globalVar1} ${globalVar2} ${localVar1} # 输出结果 Hello world 局部变量不存在
./subscript.sh # 不会将全局变量传递过去,他们是两个进程
source subscript.sh # 他们是同一个进程,可以在子脚本中使用该全局变量,会打印出Hello
# sub script
#!/bin/bash
echo "this is a sub script"
echo ${globalVar1}
echo "sub script end"
export varname=value # 将varname添加到环境变量
varname1=value
export varname1 # 将varname1添加到环境变量
#!/bin/bash
envVar="hello world"
export $envVar
# 调用子脚本
./subScript.sh # 输出 hello world
# 验证子进程中修改环境变量,父进程有没有改变
echo $envVar # 输出 hello world 子进程环境变量不会改变父进程的
# subScript.sh
#!/bin/bash
echo ${envVar}
export envVar="2222222222"
不管是环境变量还是普通的shell变量,都可以使用unset关键字进行删除。
unset varname
文件名代换,也就是 Globbing 。使用匹配的字符,也就是通配符。代换发生在命令执行之前。代换的前提是文件存在,不存在代换不了。
*.txt
?.txt
R[0-8]_[8-7]
# 下面的功能是一样的,都是创建1到4的txt文件
touch 1.txt 2.txt 3.txt 4.txt
touch {1..4}.txt
touch {1,2,3,4}.txt
mkdir -p day{1..9}/0{1_code,2_doc,3_resource,4_node}
# 创建day1到9的文件夹,并且每个文件夹中都有01_code,02_doc,03_resource,04_node四个文件夹。
使用"`"反引号括起来的也是一条命令,shell先执行该命令,然后将输出结果立即代换到当前命令中。执行某一条命令,将这个命令的标准输出的内容存储到某个变量中。
DATE=`date`
echo ${DATE}
DATE=$(date) # 和反引号的功能是一致的
# 获取当前脚本的所在目录
curPath=$(cd `dirname $0`;pwd)
# cd `dirname $0` 是进入脚本所在的目录
使用$(())
,用于算术计算,(())
中的shell变量取值将转换成整数,和同样含义的$[]
等价。
VAR=45
echo $(($VAR+3)) 等价于 $((VAR+3)) 或者 echo $[VAR+3]或 $[$VAR+3]
他们只能使用+ - * /
和()
运算符,并且只能做整数运算。$[base#n]
,其中base表示进制, n按照base进制进行解释,后面再有运算数,按十进制解释。
echo $[8#10+11] #输出 19
echo $[16#10+11] #输出 27
\
在shell中用作转移字符,用于去除紧跟其后的单个字符的特殊意义(回车除外),换句话说,紧跟其后的字符取字面值。
echo \$SHELL # 输出$SHELL
touch \$\ \$ # 创建$ $为名的文件
单引号用于保持引号内所有字符的字面值,即使引号内的\
和回车也不例外,但是字符串中不能出现单引号。
echo '$SHELL' # 输出$SHELL
echo 'ABC\
DE' # 输出ABC\回车DE
和单引号一致,但他防止通配符的扩展,允许变量的扩展。被双引号括住的内容,被视为单一字符串。
echo "$SHELL" # 输出 /bin/bash
var="a.txt b.txt"
touch $var # 创建两个文件 a.txt和b.txt
touch "$var" # 创建一个文件 名字为 a.txt b.txt
Shell 条件测试 test
用于在脚本中根据条件检查执行分支。test
命令通常以 [ ]
或者 [[ ]]
的形式出现。直接使用某条命令的返回状态表示真假,main函数返回0表示真,返回非0表示假。
检查文件是否存在:
[ -e 文件路径 ]
:如果文件存在,则返回 true。[ -f 文件路径 ]
:如果文件存在且为普通文件,则返回 true。[ -d 目录路径 ]
:如果目录存在,则返回 true。数值比较:
[ 数值1 -eq 数值2 ]
:如果两个数值相等,则返回 true。[ 数值1 -ne 数值2 ]
:如果两个数值不相等,则返回 true。[ 数值1 -lt 数值2 ]
:如果数值1小于数值2,则返回 true。[ 数值1 -le 数值2 ]
:如果数值1小于或等于数值2,则返回 true。[ 数值1 -gt 数值2 ]
:如果数值1大于数值2,则返回 true。[ 数值1 -ge 数值2 ]
:如果数值1大于或等于数值2,则返回 true。字符串比较:
[ 字符串1 = 字符串2 ]
:如果两个字符串相等,则返回 true。[ 字符串1 != 字符串2 ]
:如果两个字符串不相等,则返回 true。[ -z 字符串 ]
:如果字符串为空,则返回 true。[ -n 字符串 ]
:如果字符串非空 nonzero,则返回 true。逻辑判断:
[ 表达式1 -a 表达式2 ]
:逻辑与 and,如果两个表达式都为 true,则返回 true。[ 表达式1 -o 表达式2 ]
:逻辑或 or,如果两个表达式中至少有一个为 true,则返回 true。[ ! 表达式 ]
:逻辑非,如果表达式为 false,则返回 true。注意:[[
支持更多的高级特性,比如模式匹配和正则表达式,推荐在使用条件测试时使用 [[ ]]
。更详细的用法可以查看 Shell 的官方文档或者使用 man test
命令查看 test
命令的帮助文档。
echo $? # 打印上条命令的返回状态,0为真,1为假
( EXPRESSION ): 测试该表达式是否为真
! EXPRESSION:取反,逻辑非
EXPRESSION1 -a EXPRESSION2:and 逻辑与
EXPRESSION1 -o EXPRESSION2:or 逻辑或
-n STRING:nonzero, 判断字符串长度为非零
-z STRING:zero, 判断字符串长度为零
STRING1 = STRING2:判断字符串相等
STRING1 != STRING2:判断字符串不相等
INTEGER1 -eq INTEGER2:两个数值相等
INTEGER1 -ge INTEGER2:判断数值1大于等于数值2
INTEGER1 -gt INTEGER2:判断数值1大于数值2
INTEGER1 -le INTEGER2:判断数值1小于等于数值2
INTEGER1 -lt INTEGER2:判断数值1小于数值2
INTEGER1 -ne INTEGER2:两数值不相等
FILE1 -ef FILE2:FILE1 and FILE2 have the same device and inode numbers
FILE1 -nt FILE2:判断文件1比文件2新(最后修改时间)
FILE1 -ot FILE2:判断文件1比文件2旧(最后修改时间)
-b FILE:block,判断文件为块设备
-c FILE:character,判断文件为字符设备
-d FILE:directory,判断是否为目录
-e FILE:exist 判断文件是否存在
-f FILE:判断文件为普通文件
-g FILE:是否拥有有效组ID
-G FILE:FILE exists and is owned by the effective group ID
-h FILE:判断是否为一个符号链接 link
-k FILE:判断粘着位是否设置
-L FILE:判断是否为一个符号链接 link
-N FILE:判断文件最后一次读取后文件的长度是否大于0
-O FILE:判断文件是否有有效的用户ID
-p FILE:是不是命令管道
-r FILE:是否有读权限
-s FILE:判断文件大小是否大于0
-S FILE:判断文件是不是Socket文件
-t FD : 判断文件描述符是否被终端打开
-u FILE:判断文件用户ID是否被设置
-w FILE:判断文件是否有写权限
-x FILE:判断文件是否有可执行权限
# 语法结构
if 命令/条件测试
then
xxxxxx
elif 命令2/条件测试2 ; then # 如果then和if写在同一行需要加分号
xxxxxx
else # else不用加then
xxxxxx
fi # 将if倒着写
#!/bin/sh
if [ -f /bin/bash ]; then
echo "/bin/bash is a file"
else
echo "/bin/bash is not a file"
fi
# ":",是一个空命令,总是为真
if : # 等价于 if true
then
echo "always true"
fi
echo "Is it morning? Please answer yes or no."
read YES_OR_NO # 在终端输入一行字符串,保存到变量YES_OR_NO中
if [ "${YES_OR_NO}" = "yes" ]; then
echo "Good Morning"
elif [ "${YES_OR_NO}" = "no" ]; then
echo "Good Afternoon!"
else
echo "Sorry, ${YES_OR_NO} is not a recognized, Enter yes or no."
fi
## 在shell中 && 和 || 用于连接两条命令,分别代表逻辑与和逻辑或
## 而-a 和 -o是仅用于条件测试中来连接两条测试命令的。下面是等价的
VAR=2
test "$VAR" -gt 1 -a "$VAR" -lt 3
test "$VAR" -gt 1 && test "$VAR" -lt 3
VAR=2
if [ "$VAR" -gt 1 ] && [ "$VAR" -lt 3 ]; then
echo "true"
fi
if [ "$VAR" -gt 1 -a "$VAR" -lt 3 ]; then
echo "true"
fi
# 短路特性
make && make install # 如果make执行失败,那么不执行make install
echo xxx || exit -1 # 如果xxx执行失败,那么执行exit -1命令
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
# 语法结构
case 表达式 in
val1|pattern1)
xxxx
;;
val2|pattern2)
xxxx
;;
*)
xxxx
;;
esac # 将case倒着些
#!/bin/bash
echo "Is it morning? Please answer yes or no"
read ANSWER
case "$ANSWER" in
yes|Y|y|YES|Yes)
echo "Good Morning";;
[nN][Oo]) # 代表组合no|nO|No|NO
echo "Good Afternoon";;
*)
echo "Sorry, no recognized";;
esac
# 语法结构
for 临时变量 in 列表; do
xxxxx
done
for fruit in apple banana pear; do # do 可以单独写一行,那么就可以不需要分号了
echo "$fruit"
done
sum=0
for i in {1..100} # 循环加1-100 使用sh解释器没有花括号,使用 $(seq 1 100) 替换
do
sum=$[$sum+i]
done
echo $sum
# 遍历当前目录
for i in $(ls)
do
if [ -f "$i" ]; then
echo "$i is a file"
elif [ -d "$i" ]; then
echo "$i is a dir"
else
echo "$i no recognized"
fi
done
while 命令/条件测试 ;do # do 可以单独写一行,那么就可以不需要分号了
xxxxx
done
sum=0
count=1
while [ $count -lt 100 ]; do
sum=$(($sum+$count))
count=$(($count+1))
done
echo "sum = $sum"
他们的意义和c/c++的是一致的。
break[n] # 跳出几层循环
continue # 跳过本次循环,但不会跳出循环
#!/bin/sh
echo "input passwd"
read try
count=1
while [ "$try" != "passwd" ]; do
if [ $count -gt 5 ]; then # 等价于在while条件测试中添加 -a $count -gt 5
break
fi
echo "sorry! try against"
count=$(($count+1))
read try
done
有很多特殊变量是被shell自动赋值的
$0 # 相当于C语言main函数的argv[0]
$1、$2... # 相当于C语言main函数的argv[1]、argv[2]....
$# # 相当于C语言main函数的argc-1
$@ # 表示参数列表 "$1" "$2" "$3" ... 可以用在for循环中的in的后面
$* # 表示参数列表 "$1" "$2" "$3" ... 和$@一致
$? # 表示上一条命令的Exit Status
$$ # 当前进程号
位置参数可以使用shift
命令左移。比如shift 3
表示原来$4
现在变成了$1
,原来的$5
现在变成了$2
等等。原来的$1
、$2
、$3
被丢弃,$0
不移动。不带参数的shift
命令相当于shift 1
。也就是说shift
语句和shift 1
是等价的。位置参数最多只支持$0-$9
,所以要后面的参数,就必须shift
。
# ./shift.sh one two three four
#!/bin/sh
echo $$ # 169273
echo $@ # one two three four
echo $# # 4
echo $? # 0
echo $0 # ./shift.sh
echo $1 # one
echo $2 # two
echo $3 # three
shift 1
echo $3 # four
echo [option] string
-e 解析转义字符
-n 不回车,默认情况下echo回显内容后面跟一个回车换行
echo -e "hello\t123"
echo -n "hello"
printf "%d\t%s\r\n" 123 "hello" # 123 hello
通过|
命令把一个命令的输出传递给另一个命令做输入。原理为将前面的进程的标准输出重定向到后面进程的标准输入。
cat filename | grep "hello"
cat myfile | more
tee命令把结果输出到标准输出,另一个副本输出到相应的文件。
df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt
df -k | awk '{print $1}' | grep -v "文件系统" | tee -a a.txt # -a表示追加到a.txt后
cmd > file # 把标准输出重定向到新文件中
cmd >> file # 最加到文件中
cmd > file 2>&1 # 标准输出重定向到file文件
# 文件描述符2标准错误输出重定向到文件描述1标准输出中。
cmd < file1 > file2 # 将标准输入重定向到file1,也就是file1作为标准输入 标准输出重定向到file2
cmd < &fd # 把文件描述符fd作为标准输入
cmd > &fd # 把文件描述符fd作为标准输出
cmd < &- # 关闭标准输入
function 函数名() # 在sh解释器中没有function关键字,必须省略
{
local var=value # 局部变量
xxxx
retrun 0 # 只能返回整数,作为退出状态,不能返回其他,
# 也可以不写retrun返回,那么就以函数最后一条指令返回状态作为整个函数的退出状态
}
# 在bash解释器中,function和小括号可以省略,但是必须要有一个存在,不然无法识别为函数。
# 调用函数 函数名 arg1 arg2 arg3 ...
testfunction()
{
echo "aaaa"
return 2 # 那么此时echo $? 就是2
}
# 使用命令代换的方式获取函数的输出值aaaa
var=$((testfunction))
# 函数传参
# 在函数的内部同样是通过 $0 $1 $2 $3 .. 来获取参数
# 函数支持递归,遍历整个目录
visit()
{
local dir="$1" # 获取当前目录
for f in `ls $dir`
do
if [ -f "$dir/$f" ]; then
echo "$dir/$f is a file"
elif [ -d "$dir/$f" ]; then
echo "$dir/$f is a dir"
visit "$dir/$f" # 递归进行遍历
else
echo "$dir/$f is not regcognized"
fi
done
}
-n 读一遍脚本的命令但不执行,用于检查脚本中的语法错误
-v 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
-x 提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
sh -n script.sh # 在命令行提供参数
# 在脚本开头提供参数
#!/bin/sh -x
# 在脚本中使用set命令启动或者禁用参数
set -x # 打开调试
set +x # 关闭调试
一种匹配字符串的方法,通过一些特殊符号,实现快速查找、删除、替换某个特定字符串。是由普通字符与元字符组成的文字模式。
元字符 | 作用 |
---|---|
\ |
转义字符,用于取消特殊字符的含义,例如:\! ,\n |
^ |
匹配字符串开始的位置,如:^hello ,匹配以hello开头的行 |
$ |
匹配字符串结束的位置,如:hello$ ,匹配以hello结尾的行 |
. |
匹配除了\n 换行之外的任意一个字符 |
* |
匹配前面子表达式0次或者多次 |
[list] |
匹配list列表的一个字符,[0-9] 匹配0-9的任意一个数字 |
[^list] |
匹配不在list列表的一个字符,[^0-9] 匹配任意非数字 |
{n} |
匹配前面的表达式n次,[0-9]{2} 匹配2位数字 |
{n,} |
匹配前面的表达式不少于n次,[0-9]\{2,} 匹配2位以上的数字 |
{n,m} |
匹配前面的表达式n到m次,[a-z]{2,3} 匹配2到3位的小写字母 |
元字符 | 作用 |
---|---|
+ |
匹配前面子表达式一次以上,go+d ,将匹配至少一个o |
? |
匹配前面子表达式0次或者一次,go?d ,匹配gd 或者god |
() |
将括号中的作为一个整体,g(oo)+d ,匹配整体一次以上,例如good 、gooood |
` | ` |
在扩展正则表达式的上面添加了一些特殊字符,是最常用的。
\d 匹配一个数字的字符,和 [0-9] 语法一样
\d+ 匹配多个数字字符串,和 [0-9]+ 语法一样
\D 非数字,其他同 \d
\D+ 非数字,其他同 \d+
\w 英文字母或数字的字符串,和 [a-zA-Z0-9_] 语法一样
\w+ 和 [a-zA-Z0-9_]+ 语法一样
\W 非英文字母或数字的字符串,和 [^a-zA-Z0-9_] 语法一样
\W+ 和 [^a-zA-Z0-9_]+ 语法一样
\s 空白符号,和 [\n\t\r\f] 语法一样
\s+ 和 [\n\t\r\f]+ 一样
\S 非空白符号,和 [^\n\t\r\f] 语法一样
\S+ 和 [^\n\t\r\f]+ 语法一样
\b 匹配以英文字母,数字为边界的字符串
\B 匹配不以英文字母,数字为边界的字符串
命令 | 作用 |
---|---|
-n |
显示行号 |
-i |
不区分大小写 |
-v |
反向查找 |
以S开头的字符串:^S
以数字结尾的字符串:[0-9]$
匹配空字符串:^$
字符串只包含三个数字:^\d\d\d$ ^[0-9]{3}$ ^\d{3}$
字符串只有3到5个字母:^[a-zA-Z]{3,5}$
匹配不是a-z的任意字符串:[^a-z]
匹配有字符串0-1个数字、字母或者下划线:^[0-9a-zA-Z_]?$ ^\w?$
字符串有一个或多个空白符号(\t\n\r等): ^\s+$ ^\s{1,}$
字符串有0个或若干个任意字符(除了\n):^.{,}$ ^.*$
匹配0或任意多组ABC:^(ABC)*$
字符串要么是ABC,要么是123:^ABC$|^123$ ^(ABC|123)$
字符串只有一个点号:^[.]$
匹配十进制3位数字:^[1-9][0-9]{2}$
匹配0-999的数字:^([0-9]|[1-9][0-9]{1,2})$
匹配0-255的数字:^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$
#include
int regcomp(regex_t *preg, const char *pattern, int cflags)
编译正则表达式
preg:指向regex_t结构体的指针,用于存储编译后的正则表达式。
pattern:要编译的正则表达式字符串。
cflags:编译选项,可以使用以下常量按位或操作组合:
REG_EXTENDED:支持扩展正则表达式语法。
REG_ICASE:忽略大小写。
REG_NOSUB:不存储匹配的子字符串。
REG_NEWLINE:将'.'视为匹配任何字符,包括换行符。
int regexec(const regex_t *preg, const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags)
进行模式匹配
preg:指向编译后的正则表达式的regex_t结构体指针。
string:要匹配的字符串。
nmatch:regmatch_t结构体数组的大小,表示最多可以存储的匹配结果数量。
pmatch:存储匹配结果的regmatch_t结构体数组。
eflags:匹配选项,可以使用以下常量按位或操作组合:
REG_NOTBOL:不将字符串的开头视为行的开头。
REG_NOTEOL:不将字符串的结尾视为行的结尾。
REG_EXTENDED:使用扩展正则表达式语法。
void regfree(regex_t *preg)
当不再需要编译的正则表达式时要将其释放
preg:指向编译后的正则表达式的regex_t结构体指针。
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
errcode:错误码,通常是regcomp()或regexec()的返回值。
preg:指向编译后的正则表达式的regex_t结构体指针。
errbuf:存储错误信息的缓冲区。
errbuf_size:缓冲区的大小。
#include
#include
#include
int main(int argc, char** argv)
{
if(argc != 3)
{
printf("Uasge: %s RegexString Text \n", argv[0]);
return 1;
}
const char* pregexstr = argv[1]; // 正则的输入
const char* ptext = argv[2]; // 要匹配的文本
regex_t oregex; // 声明正则结构体
int nerrcode = 0;
char szerrmsg[1024] = {0};
size_t unerrmsglen = 0;
// 编译正则表达式
if((nerrcode = regcomp(&oregex, pregexstr, REG_EXTENDED|REG_NOSUB)) == 0)
{
if((nerrcode = regexec(&oregex, ptext, 0, NULL, 0)) == 0)
{
// 匹配成功
printf("%s matches %s\n", ptext, pregexstr);
regfree(&oregex);
return 0;
}
}
// 匹配失败
unerrmsglen = regerror(nerrcode, &oregex, szerrmsg, sizeof(szerrmsg));
unerrmsglen = unerrmsglen < sizeof(szerrmsg) ? unerrmsglen : sizeof(szerrmsg) - 1;
szerrmsg[unerrmsglen] = '\0';
printf("ErrMag: %s\n", szerrmsg);
regfree(&oregex);
return 0;
}
./a.out "^[0-9]{3}$" 123 // 输出 123 matches ^[0-9]{3}$
命令从标准输入中读取数据然后按照字符串内容进行排序
-f 忽略字符大小写
-n 比较数值的大小
-t 指定分割符,默认是空格或者tab
-k 指定分割后进行比较字段
-u 重复的行只显示一次
-r 反向排序
-R 打乱排序,同样的行洗不乱
cat test.txt | sort -u -k2 -n # 分割后按照数值比较第二列,不重复显示
cat /etc/passwd | sort -t: -k3 -n -u # 给 /etc/passwd 使用用户id排序
去除重复的行,前提是重复的行连续
-c 显示每行重复的次数
-d 仅显示重复过的行
-u 仅显示不曾重复的行
sort < test.txt | uniq
cat test.txt | sort | uniq
word count
统计数量
-l 统计行数
-c 统计字节数
-w 统计单词数
不加选项,那么就会依次输出行数、单词数、字节数
cat /etc/passwd | wc -l
是一种文本搜索工具,可以使用正则表达式搜索文本,并把匹配的行打印出来。grep
家族包含grep
、egrep
、fgrep
,egrep
是grep
的扩展,支持更多的re
元字符,fgrep
是fixed grep
,把所有的字母看作是单词,正则表达式中的元字符表示其自身的字面意义,不在特殊。Linux
的GNU
版本的grep
,功能更加的强大,通过选项 -G
、-E
、-F
来使用egrep
、fgrep
。grep
默认使用的基本的正则。
egrep = grep -E # 扩展正则
fgrep = grep -F
rgrep = grep -r
grep [options]
-c 只输出匹配行的计数
-i 不区分大小写
-h 查询多文件时,不显示文件名
-H 查询多文件时,显示文件名
-l 查询多文件时,只输出包含匹配字符的文件名
-L 列出不匹配的文件名
-n 显示匹配行以及行号
-w 只匹配整个单词,而不是字符串的一部分,例如匹配magic 那么magical就不行
-s 不显示不存在或无匹配文本的错误信息
-v 显示不包含匹配文本的所有行
-r 递归搜索某个目录下的所有文件
-F 不使用正则,使用固定字符串作为匹配
-P 使用perl正则
-E 使用扩展正则
--color=auto 可以将找到的关键字部分加上颜色显示
grep -P "\d\d" test.txt
grep -F "#include" *.c -n -H -w
find pathname -options [-print -exec -ok ...]
# 命令参数
-print find命令所查找的目录路径。例如用.表示当前目录,用/表示系统根目录,递归查找
-exec 对匹配的文件执行该参数所给出的shell命令,相应的命令的形式为'command' {} \; ,
注意{}内部无空格,和\;之间有一个空格。
find . -type f -exec ls -l {} \; # 每找到一个文件,就会执行exec后面的命令
find . -name "*.txt" -exec cp {} ./gz/ \;
-ok 和-exec的作用相同,更加安全,在执行每一个命令之前,给出提示,输入y才会执行后面的语句。
find . -name "*.txt" -ok ls -l {} \;
# options 命令选项
-name 按照文件名查找文件 find . -name "06*"
-perm 按照文件权限来查找文件 find . -perm 0064
-prune 可以使得find命令不在当前指定目录中查找,同时使用-depth,那么将被忽略
-user 按照文件属主来查找文件 find . -user root
-group 按照文件所属组来查找文件
-mtime -n/+n 按照文件的更改时间来查找文件,
-n 表示文件更改时间距现在n天以内,+n 表示文件更改时间距现在n天以前
find . -mtime -2
-atime 和mtine类似,访问时间
-ctime 和mtime类似,创建时间
-nogroup 查找无有效所属组的文件,该文件所属组在/etc/groups中不存在 find ./ -nogroup
-nouser 查找无有效属主的文件,该文件属主在/etc/passwd中不存在 find ./ -nouser
-newer file1 ! file2 查找更改时间比文件file1新但比文件file2旧的文件
-type 查找某一类型的文件
b 块设备 d 目录 c 字符设备 p 管道文件 l 符号链接文件 f 普通文件
-maxdepth find递归的最大深度
-mindepth find递归的最小深度
-depth find递归的深度
-szie n 查找文件长度为n块的文件 find ./ -size 7c
-fstype 查找某一类型文件系统中的文件
-mount 在查找文件时不跨越文件系统mount点
-follow 遇到符号链接文件跟踪至链接所指向的文件
将标准输入的参数整齐的拼凑在一行里边。一般需要配合其他命令使用
cat test.txt | xargs touch
# 加入test.txt内容
a
b
c
# 上面的命令解释为 touch a b c, 即将cat test.txt | xargs产生的全部内容放到最后面
find . -name "*.sh" | xargs mv -I{} mv {} ./test
# 其中的-I{} 表示使用{}来表示find . -name "*.sh" | xargs产生的全部内容,假设为a
# 那么就相当于 mv a ./test
sed意为流处理器,将前一个程序的输出引入sed的输入,经过一系列的编辑命令转换为另一种格式输出。文本1 -> sed + 脚本 -> 文本2。sed以行为单位处理文件。
sed option 'script' file1 file2 ....
sed option -f scriptfile file1 file2 ....
sed '/pattern/actions' file1 file2 ... # pattern正则表达式 actions匹配成功后的动作
sed -n '2p' test.txt # 输出 test.txt 的第二行
sed '2d' test.txt # 删除第二行
sed '$d' test.txt # 删除最后一行
sed '2,5d' test.txt # 显示删除2到5行的结果
sed '/12/d' test.txt # 匹配到12就删除该行,显示其他结果
# p(print)打印 i(inserd)插入 a(append)追加 d(delete)删除 s(substition)替换
sed '2i aasscc' test.txt # 在第二行插入 aasscc
sed 's/123/567/' test.txt # 将文本中的123替换为567
sed -n test.txt # 静默输出
-e 允许多个脚本指令被执行
-i 直接修改源文件
-r 在脚本指令中使用扩展正则表达式
-s 将指定的多个文件允许把他们当作单独的文件,正则表达式则不进行跨文件匹配
-u 最低限度的缓存输入输出
不仅能以行为单位还能以列为单位处理文件。awk缺省的行分隔符是换行,缺省的列分隔符是连续空格或者tab。但是行分隔符和列分隔符都可以自己定义。
awk option 'script' file1 file2 ....
awk option -f scriptfile file1 file2 ....
/pattern/{actions} # 满足pattern正则执行actions
condition/{actions} # 满足condition条件执行actions
{actions} # 对每一行都进行处理执行actions
BEGIN {action} # 在遍历文本第一行之前执行某个动作
END {action} # 在遍历完文本执行某个动作
cat /etc/passwd | awk -F: '{print $3}' # -F:分隔符为: 打印第三列 $0表示当前行
awk '{print $1}' test.txt # 打印第一列
awk '/^Pro/{print $2}' test.txt # 开头匹配到Pro的行打印第二列
# 第二列小于75打印当前行和REORDER,大于等于的打印当前行
awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {printf "%s\n", $0;}' test.txt
BEGIN{
printf "%s\t%s\n", "产品", "库存";
sum=0;
}
{
printf "%s\t%s" ,$1 ,$2;
sum+=$2;
}
END{
printf "库存总量:%d\n", sum;
}
linux 系统定时器
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
每小时的第17分钟,root去执行后面的指令
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
每天的凌晨6点25分的时候,root去执行后面的指令
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
每周的星期天的6点47,root去执行后面的指令
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
每月中的第一天的6点52,root去执行后面的指令
# 先执行crontab –e在添加,或者直接vim /etc/crontab
crontab –e : 修改 crontab 文件. 如果文件不存在会自动创建。
crontab –l : 显示 crontab 文件。
crontab -r : 删除 crontab 文件。
crontab -ir : 删除 crontab 文件前提醒用户。