路径与指令的搜寻顺序
alias-builtin-$PATH
万用字元与特殊符号
万用符号:
signal | mean |
---|---|
* | 代表0到无穷个任意字元 |
? | 代表一定有一个 任意字元 |
[ ] | 一定有一个在括号内的字元,[ABCD]代表ABCD中任何一个字元 |
[ - ] | 在编码顺序内的所有字元,[1-9] |
[^ ] | “非”,反向选择 |
特殊符号:
signal | mean |
---|---|
# | 注释 |
\ | 跳脱符号、将特殊外用符号转换为一般字元 |
pipe | 管道 |
~ | user的家目录 |
$ | 取用变数前置字元 |
& | job control |
! | 非 |
/ | 路径分割符 |
>、>> | 输出导向 |
< | 输出导向 |
’ ’ 、“ ” | 单引号不具有变数转置功能,双引号具有该功能 |
() | 字shell的起始和结束 |
{ } | 命令区块的组合 |
ll -d /etc/cron*
ll -d /etc/?????
ll -d /etc/*[0-9]*
ll -d /etc/[^a-z]*
mkdir /tmp/upper; cp -a /etc/[^a-z]* /tmp/upper
资料流重导向
type | content |
---|---|
标准输入(stdin) | 指令执行所回传的正确讯息;代码为0;使用<或<< |
标准输出(stdout) | 代码为1;使用>或>> |
标准错误(stderr) | 指令执行失败后,所回传的错误讯息;代码为2;使用2>或2>> |
将stdout与stderr分存到不同的档案中
find /home -name .bashrc > list_right 2>list_error
/dev/null垃圾桶黑洞装置与特殊写法
将错误的资料丢弃,荧幕只显示正确的资料
find /home -name .bashrc 2>/dev/null
将错误的与正确的资料写到同一个档案
find /home -name .bashrc > list 2>&1
find /homw -name .bashrc &>list
standard input:<、<<
同cat建立一个档案
cat > filename
xxxx
xxxxx
按下[Ctrl]+d退出
用某个档案的内容来取代键盘的敲击
cat > file1 <file2
cat > file <<eof
xxxxxx
xxxxxx
eof
命令执行的判断依据:; && ||
一次执行多个命令:
command1;command2;command3
指令回传值$?与&&与||
若前一个指令执行正确,会返回 $?=0
查阅目录是否存在,若存在就建立一个文件
ls /tmp/abc && touch /tmp/abc/hehe
查阅目录是否存在,不存在就建立
ls /tmp/abc || mkdir /tmp/abc
不确定某目录是否存在,但就是要建立文件
ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe
管道命令(pipe)
管道命令与 连续下达命令是不一样的。
管道命令 | 仅能处理由前面一个指令传来的正确资讯,也就是stdout的资讯,对stderr没有直接处理的能力。
撷取命令: cut
cut可以将一段讯息的某一段给他 切出来,处理的讯息是以行为单位。
cut [-dfc]
option | mean |
---|---|
-d | 指定分割符 |
-f | 用-f取出第几段的意思,从1开始 |
-c | 以characters的单位取出固定字元区间。n-、n-m、-m |
echo $PATH | cut -d ':' -f 5 取出第五段
echo $PATH | cut -d ':' -f 3,5 取出第三和五段
export | cut -c 12- 取出第12字元以后的所有字串
撷取命令: grep
grep [-acinv] [–color=auto] ‘搜寻字串’ filename
option | mean |
---|---|
-a | 将binary档案以text档案的方式搜寻资料 |
-c | 计算找到的次数 |
-i | 忽略大小写不同 |
-n | 顺便输出行号 |
-v | 反向选择,显示没有搜寻字串的行 |
–color=auto | 找到的关键字部分加上颜色的显示 |
取last中出现root的行
last | grep 'root'
取last中没有root的行
last | grep -v 'root'
取出现root的行的第一栏
last | grep 'root' | cut -d ' ' -f1
排序命令:sort
sort [-nrktufM] file or stdin
option | mean |
---|---|
-n | 数值排序 |
-r | 反向排序 |
-k | 指定区间field排序 |
-t | 指定分割符,预设用tab分割 |
-u | uniq,相同的资料只出现一行代表 |
-f | 忽略大小写差异 |
-M | 以月份名字排序 |
个人帐号都记录在/etc/passwd下,请将帐号进行排序。
cat /etc/passwd | sort
/etc/passwd内容是以:来分隔的,以第三栏来排序
cat /etc/passwd | sort -t ":" -k 3,3
使用数字排序
cat /etc/passwd | sort -t ":" -k 3,3n
取帐号,并加以排序
last | cut -d " " -f1 | sort
处理重复:uniq
uniq [-ic] 重复的行删除只显示一个
option | mean |
---|---|
-i | 忽略大小写 |
-c | 计数 |
last | cut -d ' ' -f1|sort|uniq
last | cut -d ' ' -f1|sort|uniq -c
wc
wc [-lwm]
option | mea |
---|---|
-l | 计算行数 |
-w | 计算英文单字 |
-m | 计算字元 |
双向重导向:tee
tee [-a] file
-a:以append方式将资料追加到file当中
last | tee last.list | cut -d " " -f1
ll /home | tee ~/homefile | more
ll / | tee -a ~/homefile |more
tr:删除、替换文字讯息
tr [-ds] set1
option | mean |
---|---|
-d | 删除讯息当中set1这个字串 |
-s | 取代掉重复的字元 |
last | tr '[a-z]' '[A-Z]'
cat /etc/passwd | tr -d ':'
join:两个档案中有相同的资料那一行,将它们加起来
join [-ti12] file1 file2
option | mean |
---|---|
-t | 分割符 |
-i | 忽略大小写差异 |
-1 n | 第一个file分析的栏位 |
-2 n | 第二个file分析的栏位 |
join -t ':' /etc/passwd /etc/shadow |head -n 3
join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3
paste:将两行贴在一起,且中间以Tab键隔开
paste [-d] file1 file2
-d:指定分割符,默认用tab
-:如果file部分写成 -,表示来自stdin的资料
分割命令:split
split [-lb] file PREFIX
option | mean |
---|---|
-l n | 以行数进行分割 |
-b | 以档案大小进行分割,可加单位:b k m |
PREFIX | 作为分割档案的前导文字 |
split -b 300k /etc/service services
cat services*>>servicesback
ls -al | split -l 10 - lsroot
参数代换:xargs
用来产生某个指令的参数
xargs [-0epn] command
option | mean |
---|---|
-0 | 将stdin中特殊字元还原成一般字元 |
-e | EOF,后面接一个字串;分析到这个字串时就会停止 |
-p | 执行每个arg询问意见 |
-n | 后面接times,指定使用几个参数 |
减号-的用途
使用到前一个指令的stdout 作为这次的stdin
grep进阶选项
grep [-A] [-B] [–color=auto] ‘搜寻字串’ filename
option | mean |
---|---|
-A(after) | 除了列出该行,后续n行也列出来 |
-B(before) | 除了列出该行,前面的n行也列出来 |
dmesg | grep 'qxl'
dmesg | grep -n --color=auto 'qxl'
dmesg | grep -n -A3 -B2 --color=auto 'qxl'
基础正则表达式练习
搜寻特定字串the
grep -n ‘the’ regular_express.txt
反向选择
grep -nv 'the' regular_express.txt
忽略大小写
grep -ni 'the' regular_express.txt
利用中括号:搜寻test或tast
grep -n 't[ae]st' regular_express.txt
想要搜寻有oo的字元
grep -n 'oo' regular_express.txt
搜寻有oo前面不能是g的字元
grep -n '[^g]oo' regular_express.txt
取得有数字的一行
grep -n '[0-9]' regular_express.txt
取得oo前面不是小写字元的列
grep -n '[^a-z]oo' regular_express.txt
grep -n '[^[:lower:]]oo' regular_express.txt
the只出现在行首
grep -n '^the' regular_express.txt
开头是小写字元
grep -n '^[a-z]' regular_express.txt
grep -n '^[[:lower:]]' regular_express.txt
行尾结尾是小数点的行
grep -n '\.$' regular_express.txt
取出空白行
grep -n '^$' regular_express.txt
过滤空白行和注释行
grep -v ‘^$’ file | grep -v "^#"
字元 | 意义 |
---|---|
. | 一个任意字元 |
* | 重复前一个字元,0到无穷多次 |
要找出开头g结尾d的字元,共四个字
grep -n ‘g..d’ regular_express.txt
至少两个o以上的字串
grep -n 'ooo*' regular_express.txt
以g开头结尾,中间可有可无
grep -n "g.*g" regular_express.txt
要让{生效,要加上反斜线,即要使用 { 才能成功的让限定连续RE字符范围生效
要找两个o的字串
grep -n 'o\{2\}' regular_express.txt
要找g后面接2到5个o的字串
grep -n 'go\{2,5\}g' regular_express.txt
的是2 个o 以上的字串
grep -n 'o\{2,\}' regular_express.txt
基础正则表达式字符汇整
RE | mean |
---|---|
^word | 待搜索word在行首 |
word$ | 待搜索word在行尾 |
. | 代替任意一个字元 |
\ | 去除特殊意义 |
* | 重复0到无穷多个前一个字符 |
[list] | 取list中任意一个 |
[n1-n2] | 列出想要撷取的字元范围 |
[^list] | 非,列出不要的字串或范围 |
{n,m} | 连续n到m个的『前一个RE字符』 |
Sed工具
sed [-nefri] [动作]
option | mean |
---|---|
-n | silent;只列出只经过sed特殊处理的那一行 |
-e | 直接在指令列模式进行动作编辑 |
-f | -f filename,将sed的动作写在file里 |
-r | sed的动作支援是延伸性正规表示法 |
-i | 直接修改读取文档内容,不由屏幕输出 |
动作说明:[n1,[,n2]]function
function:
function | mean |
---|---|
s | 取代替换 |
d | 删除 |
p | 打印,与sed -n配合使用 |
c | 取代 |
y | |
i | 向前插入 |
a | 向后插入 |
例子:
将/etc/passwd的内容列出并且列出行号,同时删除第2-5行
nl /etc/passwd | sed '2,5d'
删除第二行
nl /etc/passwd | sed '2d'
删除第三行到最后一行
nl /etc/passwd | sed '3,$d'
在第二行后加上drink tea?
nl /etc/passwd | sed '2a drink tea'
在第二行后加上drink tea or … 与drink beer
nl /etc/passwd | sed '2a drink tea or ....\ drink beer'
将2-5行的内容取代为No 2-5 number
nl /etc/passwd | sed '2,5c No 2-5 number'
仅列出档案内的第5-7行
nl /etc/passwd | sed -n '5,7p'
延伸正规表示法
grep 预设仅支援基础正规表示法,如果要使用延伸型正规表示法,你可以使用grep -E , 不过更建议直接使用egrep
sed -r
RE | mean |
---|---|
+ | 重复 一个或一个以上的 前一个re字符 |
? | 0或1个前一个re字符 |
| | or |
() | 找出群组字串 |
()+ | 多个重复群组 |
! 在正规表示法当中并不是特殊字元,表示非用^
格式化列印:printf
printf ‘列印格式’ 实际内容
format | mean |
---|---|
%ns | n个string |
%ni | n个integer |
%N.nf | N总位数,n小数点数 float |
\t | 水平tab |
\v | 垂直tab |
\r | Enter |
\n | 输出新的一行 |
awk:好用的资料处理工具
awk ‘条件类型1{动作1}条件类型2{动作2}…’ filename
awk主要是处理『每一行的栏位内的资料』,而预设的『栏位的分隔符号为"空白键"或"[tab]键" 』
diff:比对两个档案的差异
diff [-bBi] from-file to-file
option | mean |
---|---|
from-file | 原始比对档案 |
to-file | 目的比对档案 |
-b | 忽略一行当中,多个空白差异 |
-B | 忽略空白行差异 |
-i | 忽略大小写差异 |
cmp:利用位元组比对两个档案
cmp [-l] file1 file2
-l:将所有不同的位元组处都列出来
Shell Script
第一支script:
content | description |
---|---|
#!/bin/bash | 宣告script使用的shell名称 |
# | 注释作用 |
History、Date、Author | 程式内容说明 |
PATH= | 主要环境变量的宣告 |
echo | 主要程式部分 |
exit 0 | $?获取,exit使程式中断并且回传一个数值给系统 |
程序执行:
chmod a+x hello.sh
./hello.sh
良好习惯
简单范例:
变数内容由使用者决定:
read -p "Please input your first name:" firstname
read -p "please input your last name:" lastname
echo -e "\nYour full name is: ${firstname} ${lastname}"
利用date进行档案的建立
echo -e "i will usr 'touch' command to create 3 files"
read -p "please input your filename:" fileuser
date1=$(date --date='2 days ago' +%Y%m%d) #前两天的日期
date2=$(date --date='1 days ago' +%Y%m%d #前一天的日期
date3=$(date +%Y%m%d) #今天的日期
file1=${filename}${date1}
touch "${file1}"
使用者输入两个变数,然后将两个变数的内容相乘,最后输出相乘的结果
read -p "Enter the first number:" firstnum
read -p "Enter the second number:" secondnum
total=$((${firstnum} * ${secondnum}))
echo -e "\n The result of ${firstnum} x ${secondnum} is ==> ${total}"
script的执行方法的差异(source、sh script、./script)
(1) sh script:在脚本设定好的变数在bash环境下无效,因为script执行完毕之后子程序bash内所有资料都会被移除。
(2)source script:在父程序执行脚本,script设定的变数会保留
善用判断式
利用test指令的测试功能
检查/dmtsai 是否存在
test -e /dmtsai
检查/dmtsai是否存在,有回复
test -e /dmtsai && echo "exist" || echo "Not exist"
关于某个档名的类型判断
option | mean |
---|---|
-e | 档名是否存在 |
-f | 档名是否存在且为file |
-d | 档名是否存在且为direcory |
-b | 档名是否存在且为block device |
-c | 档名是否存在且为character device |
-S | 档名是否存在且为Socket |
-p | 档名是否存在且为pipe |
-L | 档名是否存在且为一个连接档 |
关于档案的权限
option | mean |
---|---|
-r | 档名是否存在且可读 |
-w | 档名是否存在且可写 |
-x | 档名是否存在且可执行 |
-u | 档名是否存在且具有SUID属性 |
-g | 档名是否存在且具有GUID属性 |
-s | 档名是否存在且为 非空白档案 |
两个档案之间的比较
option | mean |
---|---|
file1 -nt file2 | file1是否比file2新 |
file1 -ot file2 | file1是否比file2旧 |
file1 -ef file2 | file1与file2是否为同一个档案(是否有同一个inode) |
关于两个整数之间的判定
option | mean |
---|---|
-eq | equal |
-ne | not equal |
-lt | less then |
-le | less than or equal |
-gt | greater than |
-ge | greater than or equal |
判定子串的资料
option | mean |
---|---|
test -z string | 判断子串是否为0?若string为空字符串返回True |
test -n string | 判断子串是否不为0;若string为空字串返回False |
test str1 == str2 | 判断str1是否等于str2 |
test str1 != str2 | 判断str1是否不等于str2 |
多重条件判断
option | mean |
---|---|
-a | 两种状况同时成立。test -r file -a -x file |
-o | 两种状况任何一个成立。 test -r file -o -x file |
! | 反向状态 test ! -x file |
让使用者输入档名,并且判断使用者是否真的有输入字串?
echo -e "please input a filename,I will check the filename's type and permission.\n\n"
read -p "Input a filename:" filename
test -z ${filename} && echo "you must input a filename." && exit 0
判断档案是否存在?若不存在则显示讯息并结束脚本
test -e ${filename} && echo "The filename '${filename}' DO NOT exits" && exit 0
开始判断档案类型与属性
test -f ${filename} && filetype="regular file"
test -d ${filename} && filetype="directory"
test -r ${filename} && perm="readable"
test -w ${filename} && perm="${perm} writable"
test -x ${filename} && perm="${perm} executable"
利用判断符号[]’
中括号的两端需要有空白字元来分割;
中括号内变数最好用双引号括号起来;
在中括号中内的常数最好都以单双引号括起来。
name ="VBird Tsai"
[ "${name}" == "VBird" ]
执行一个程式的时候,这个程式会让使用者选择Y或N,
当使用者输入Y或y的时候就显示 OK,continue
当使用者输入N或n的时候就显示 Oh,intettupt
如果不是就显示 I don’t know what your choice is
read -p "Enter your choice(Y/N):" choice
[ "${choice}" == "Y" -o "${choice}" == "y" ] && echo "Ok,continue" && exit 0
[ "${choice}" == "N" -o "${choice}" == "n" ] && echo "Oh,interrupt" && exit 0
echo "I don't know what your choice is " && echo 0
Shell script的预设变量($0,$1)
$0是执行的脚本文档名,$1之后的是参数
mean | |
---|---|
$n | n代表后接参数的个数,$4表示第四个参数 |
“$@” | 代表["$1" “$2” “$3” “$4”],每个变量都是独立的 |
“$*” | 代表["$1c$2c$3c$4"],c为分割字元,预设是空白键 |
$# | 参数总个数 |
echo "The script name is ==> ${0}"
echo "Total parameter number is $#"
echo "Your whole parameter is ==> '$@' "
echo "The first parameter is ${1}"
shift:造成参数变数号码偏移
shift:拿掉最前面的一个参数
shift n:拿到最前面的n个参数
条件判断式
&&代表AND; || 代表OR
if [condition] ; then
command;
fi
用以上的语法改写NY题
read -p "Enter your choice(Y/N):" choice
if [ "${choice}" == "Y" ] || [ "${choice}" == "y"];then
echo "OK,continue";
exit 0;
fi
if [ "${choice}" == "N" ] || [ "${choice}" == "n"];then
echo "Oh.interrupt";
exit 0;
fi
echo "I don't know what your choice is" && exit 0
多重、复杂条件判断式
一个条件判断,分成功进行与失败进行
if [condition]; then
command;
else
command;
fi
多个条件判断,分多钟不同的情况
if [condition1];then
command1;
elif [conditon2];then
command2;
else
command3;
fi
改写NY题
read -p "Enter your choice(Y/N):" choice
if [ "${choice}" == "Y" ] || [ "${choice}" == "y" ]; then
echo "Ok,continue";
elif [ "${choice}" == "N" ] || [ "${choice}" == "n" ]; then
echo "Oh,interrupt";
else
echo "I don't know what your choice is";
fi
if [ "${1}" == "hello" ]; then
echo "Hello,how are you?";
elif [ "${1}" == "" ]; then
echo "You must input parameters";
else
echo "The only parameter is 'hello',ex>{${0} hello}";
fi
利用case … esac判断
case $variable in
"第一个变量内容")
command1
;;
"第二个变量内容")
command2
;;
*)
command3
;;
esac
改写
case ${1} in
"hello")
echo "hello,how are you?"
;;
"")
echo "you must input parameters"
;;
*)
echo "Usage ${0} {hello}"
;;
esac
利用function功能
function fname () {
command
}
回圈loop
while do done;until do done(不定回圈)
当conditon条件成立时,就进行回圈,直到condition的条件不成立时才停止
while [condition]
do
command
done
当condition条件成立时,就停止回圈,否则就持续进行回圈的程式段
until [condition]
do
command
done
计算1+2+…+100
total=0
i=0
while [ "${i}" != '100' ]
do
i=$((1+$i))
total=$(($total+$i))
done
for do done(固定回圈)
for var in con1 con2 con3...
do
command
done
for animal in dog cat elephant
do
echo "There are ${animal}s ..."
done
提取etc/passwd的账号,并逐行打印出来
users=$(cut -d ":" -f1 /etc/passwd)
for username in ${user}
do
id($username)
done
for do done的数值处理
for ((初始值;限制值;执行步阶))
do
command
done
arg | mean |
---|---|
初始值 | 某个变数在回圈当中的起始值,类似 i=1 |
限制值 | 当变数的值在这个限制值的范围内,就继续进行回圈。例如 i<=100 |
执行步阶 | 每做一次回圈,变数的变化量。i=i+1 |
read -p "Please input a number,i will count for 1+2..+your_input:" num
for (( i=1 ; i<=${num}; i++ ))
do
s=$(( ${s} +${i} ))
done