linux基础一篇就够了

时间:2022-05-30 16:44:48

Linux学习笔记
粗略笔记第一版,全文约2000行50000字

1、 时间和日历

date:查看当前时间

linux基础一篇就够了

cal:查看当月日历

linux基础一篇就够了

cal 2018:查看年日历

linux基础一篇就够了

cal 10 2018:指定某年某月日历

linux基础一篇就够了

2、 计算器

bc:进入计算器模式

linux基础一篇就够了

使用ctrl+z 或者 quit退出计算器模式

3、 组合快捷键

tab:补全命令(如使用cd 打开名字为abcd的一个文件,输入了 cd ab按下tab,自动补全,如果存在多个名称相同不可行)。

Ctrl+c和ctrl+z都是中断命令,但是他们的作用却不一样.

Ctrl+C:是强制中断程序的执行。

Ctrl+Z:的是将任务中断,但是此任务并没有结束,他仍然在进程中他只是维持挂起的状态。

Ctrl+D:直接退出终止程序

man:类似与其他工具的help(如man date,显示date的帮助文档)

linux基础一篇就够了

按键 进行工作

空格键	向下翻一页
[Page Down] 向下翻一页
[Page Up] 向上翻一页
[Home] 去到第一页
[End] 去到最后一页
/string 向『下』搜寻 string 这个字符串,如果要搜寻 vbird 的话,就输入 /vbird
?string 向『上』搜寻 string 这个字符串
n, N 利用 / 或 ? 来搜寻字符串时,可以用 n 来继续下一个搜寻 (不论是 / 或 ?) ,可以利用 N 来进行『反向』搜寻。举例来说,我以 /vbird 搜寻 vbird 字符串, 那么可以 n 继续往下查询,用 N 往上查询。若以 ?vbird 向上查询 vbird 字符串, 那我可以用 n 继续『向上』查询,用 N 反向查询。
q 结束这次的 man page

4、用户

1、获取Ubuntu root密码

安装完Ubuntu后忽然意识到没有设置root密码,不知道密码自然就无法进入根用户下。到网上搜了一下,原来是这麽回事。Ubuntu的默认root密码是随机的,即每次开机都有一个新的root密码。我们可以在终端输入命令 sudo passwd,然后输入当前用户的密码,enter,终端会提示我们输入新的密码并确认,此时的密码就是root新密码。修改成功后,输入命令 su root,再输入新的密码就ok了。

2、Linux里查看所有用户

(1)在终端里.其实只需要查看 /etc/passwd文件就行了.

(2)看第三个参数:500以上的,就是后面建的用户了.其它则为系统的用户.

1、查看所有用户:cat /etc/passwd |cut -f 1 -d :

2、查看所有组:cat /etc/group

3、切换用户

使用su命令

直接使用su –是切换到root

示例:su root 切换到root用户,会提示输入密码然后就会成功切换

回到当前登录用户命令:exit

1、后台任务

ctrl + z可以将一个正在前台执行的命令放到后台,并且处于暂停状态,不可执行

jobs 查看后台在运行的工作

输入ps查看后台所以进程

输出结果:

目前,该终端下有三个进程: bash、a.out、ps

PID TTY TIME CMD

2745 pts/1 00:00:00 bash

3960 pts/1 00:00:00 a.out

3961 pts/1 00:00:00 ps

我们将关闭a.out进程。

通过ps查到a.out进程的进程号PID是3960

kill -s 9 3960

就可以关闭a.out

如果您想关闭其他进程,只要将3960换成别的进程的进程号就可以了。

2、查看某程序安装路径

whereis 程序名称

4、创建用户组和用户

1、 组的概念

用户组(group)就是具有相同特征的用户(user)的集合体;比如有时我们要让多个用户具有相同的权限,比如查看、修改某一文件或执行某个命令,这时我们需要用户组,我们把用户都定义到同一用户组,我们通过修改文件或目录的权限,让用户组具有一定的操作权限,这样用户组下的用户对该文件或目录都具有相同的权限,这是我们通过定义组和修改文件的权限来实现的。一个用户可以同时属于多个组。

举例:我们为了让一些用户有权限查看某一文档,比如是一个时间表,而编写时间表的人要具有读写执行的权限,我们想让一些用户知道这个时间表的内容,而不让他们修改,所以我们可以把这些用户都划到一个组,然后来修改这个文件的权限,让用户组可读,这样用户组下面的每个用户都是可读的。

2、 创建新用户

useradd 用户名(以A为例)//创建用户 A

passwd 用户名(以A为例)//给用户A设置密码

当前用户直接passwd(如首次使用root可直接设置新密码)

3、 新建组

groupadd 组名(以A为例)//创建组A

4、 创建用户的同时加入某个组

useradd -g 组名(以A为例) 用户名(以B为例)//创建用户A,并将其加入组B

5、 给已有的用户增加工作组

usermod -g 组名(A) 用户名(B)//将A加入组B

或者

gpasswd -a 用户名 组名

6、永久性删除用户

userdel 用户名(A)//删除用户A

groupdel 组名(B)//删除组B

7、从组中删除用户

gpasswd -d 用户名 组名

8、用户组常用命令

groups 查看当前登录用户的组内成员

groups test 查看test用户所在的组,以及组内成员

whoami 查看当前登录用户名

linux基础一篇就够了

9、修改用户组名称:groupmod -n 新组名 原组名

10、修改组编号:groupmod -g 要修改的组编号 组名

11、锁定账户:passwd -l 用户名

12、解锁账户:passwd -u 用户名

13、清除账户密码(可以无密码登录):passwd -d 用户名

5、查看用户登录数

查看用户

whoami #要查看当前登录用户的用户名

who am i #表示打开当前伪终端的用户的用户名

who mom likes

who 命令其它常用参数

参数 说明

-a 打印能打印的全部

-d 打印死掉的进程

-m 同am i,mom likes

-q 打印当前登录用户数及用户名

-u 打印当前登录用户登录信息

-r 打印运行等级

5、 文件操作及权限

linux基础一篇就够了

1、查看文件详细

可使用:ls 普通信息,ll 详细信息 ,

ls-a 横向显示所有文件包括隐藏文件

ls –al纵向显示所有文件包括隐藏文件

ubuntu中ll就会显示所有文件包括隐藏文件

2、类型与权限

linux基础一篇就够了

• r (read):可读取此一档案的实际内容,如读取文字档的文字内容等;

• w (write):可以编辑、新增或者是修改该档案的内容(但不含删除该档案);

• x (eXecute):该档案具有可以被系统执行的权限。

• 第一个字元代表这个档案是『目录、档案或连结档等等』:

当为[ d ]则是目录,例如上表档名为『.config』的那一行;
当为[ - ]则是档案,例如上表档名为『initial-setup-ks.cfg』那一行;
若是[ l ]则表示为连结档(link file);
若是[ b ]则表示为装置档里面的可供储存的周边设备(可随机存取装置);
若是[ c ]则表示为装置档里面的序列埠设备,例如键盘、滑鼠(一次性读取装置)。

例:

若有一个档案的类型与权限资料为『-rwxr-xr–』,请说明其意义为何?

先将整个类型与权限资料分开查阅,并将十个字元整理成为如下所示:

[-][rwx][rx][r–]

1 234 567 890

1为:代表这个档名为目录或档案,本例中为档案(-);
234为:拥有者的权限,本例中为可读、可写、可执行(rwx);
567为:同群组使用者权限,本例中为可读可执行(rx);
890为:其他使用者权限,本例中为可读(r),就是唯读之意

同时注意到,rwx所在的位置是不会改变的,有该权限就会显示字元,没有该权限就变成减号(-)就是了。

目录与档案的权限意义并不相同,这是因为目录与档案所记录的资料内容不相同所致。由于目录与档案的权限意义非常的重要

查看文档详细修改时间:ls -l --full-time

例:

假设test1, test2, test3同属于testgroup这个群组,如果有下面的两个档案,请说明两个档案的拥有者与其相关的权限为何?

-rw-r–r-- 1 root root 238 Jun 18 17:22 test.txt

-rwxr-xr-- 1 test1 testgroup 5238 Jun 19 10:25 ping_tsai

答:

• 档案test.txt的拥有者为root,所属群组为root。至于权限方面则只有root这个帐号可以存取此档案,其他人则仅能读此档案;

• 另一个档案ping_tsai的拥有者为test1,而所属群组为testgroup。其中:

test1 可以针对此档案具有可读可写可执行的权力;
而同群组的test2, test3两个人与test1同样是testgroup的群组帐号,则仅可读可执行但不能写(亦即不能修改);
至于没有加入testgroup这一个群组的其他人则仅可以读,不能写也不能执行!

例:

承上一题如果我的目录为底下的样式,请问testgroup这个群组的成员与其他人(others)是否可以进入本目录?

drwxr-xr-- 1 test1 testgroup 5238 Jun 19 10:25 groups/

答:

• 档案拥有者test1[rwx]可以在本目录中进行任何工作;

• 而testgroup这个群组[rx]的帐号,例如test2, test3亦可以进入本目录进行工作,但是不能在本目录下进行写入的动作;

• 至于other的权限中[r–]虽然有r ,但是由于没有x的权限,因此others的使用者,并不能进入此目录!

3、更改文件读写权限

linux基础一篇就够了

权限 数字

r  4

w  2

x  1

-rw——- (600) 只有所有者才有读和写的权限
-rw-r–r– (644) 只有所有者才有读和写的权限,组群和其他人只有读的权限
-rwx—— (700) 只有所有者才有读,写,执行的权限
-rwxr-xr-x (755) 只有所有者才有读,写,执行的权限,组群和其他人只有读和执行的权限
-rwx–x–x (711) 只有所有者才有读,写,执行的权限,组群和其他人只有执行的权限
-rw-rw-rw- (666) 每个人都有读写的权限
-rwxrwxrwx (777) 每个人都有读写和执行的权限

实例

修改文件可读写属性的方法

『 chmod 754 filename』

例如:把index.html 文件修改为可写可读可执行:

chmod 777 index.html

要修改目录下所有文件属性可写可读可执行:

chmod 777 *.*

把文件夹名称与后缀名用*来代替就可以了。

比如:修改所有htm文件的属性:

chmod 777 *.htm

修改文件夹属性的方法

把目录 /images/xiao 修改为可写可读可执行

chmod 777 /images/xiao

修改目录下所有的文件夹属性

chmod 777 *

把文件夹名称用*来代替就可以了

要修改文件夹内所有的文件和文件夹及子文件夹属性为可写可读可执行

chmod -R 777 /upload

drwxr–r-- 3 root root 4096 Jun 25 08:35 .ssh

系统有个帐号名称为vbird,这个帐号并没有支援root群组,请问vbird对这个目录有何权限?是否可切换到此目录中?

答:

vbird对此目录仅具有r的权限,因此vbird可以查询此目录下的档名列表。因为vbird不具有x的权限,亦即vbird 没有这个抽屉的钥匙啦!因此vbird并不能切换到此目录内!(相当重要的概念!)

假设有个帐号名称为dmtsai,他的家目录在/home/dmtsai/,dmtsai对此目录具有[rwx]的权限。若在此目录下有个名为the_root.data的档案,该档案的权限如下:

-rwx------ 1 root root 4365 Sep 19 23:20 the_root.data

请问dmtsai对此档案的权限为何?可否删除此档案?

答:

如上所示,由于dmtsai对此档案来说是『others』的身份,因此这个档案他无法读、无法编辑也无法执行,也就是说,他无法变动这个档案的内容就是了。

但是由于这个档案在他的家目录下,他在此目录下具有rwx的完整权限,因此对于the_root.data这个『档名』来说,他是能够『删除』的!结论就是,dmtsai这个用户能够删除the_root.data这个档案!

文档只要具有x 即可!r 是非必备的!只是,没有r 的话,使用[tab] 时,他就无法自动帮你补齐档名了

4、文件后缀区分

1、 *.sh : 脚本或批次档(scripts),因为批次档为使用shell写成的,所以副档名就编成.sh 啰;

2、 *Z, *.tar, *.tar.gz, *.zip, *.tgz: 经过打包的压缩档。这是因为压缩软体分别为gunzip, tar 等等的,由于不同的压缩软体,而取其相关的副档名啰!

3、 *.html, *.php:网页相关档案,分别代表HTML 语法与PHP 语法的网页档案啰!.html 的档案可使用网页浏览器来直接开启,至于.php 的档案, 则可以透过client 端的浏览器来server 端浏览,以得到运算后的网页结果呢!

5、Linux档案名称的限制

由于Linux在文字介面下的一些指令操作关系,一般来说,你在设定Linux底下的档案名称时, 最好可以避免一些特殊字元比较好!例如底下这些:

  • ? > < ; & ! [ ] | \ ’ " ` ( ) { }

    因为这些符号在文字介面下,是有特殊意义的!另外,档案名称的开头为小数点『.』时, 代表这个档案为『隐藏档』喔!同时,由于指令下达当中,常常会使用到-option 之类的选项, 所以你最好也避免将档案档名的开头以- 或+ 来命名啊!

6、 目录树架构示意图

例題:

網路文件常常提到類似『./run.sh』之類的資料,這個指令的意義為何?

答:

由於指令的執行需要變數(bash章節才會提到)的支援,若你的執行檔放置在本目錄,並且本目錄並非正規的執行檔目錄(/bin, /usr/bin等為正規),此時要執行指令就得要嚴格指定該執行檔。『./』代表『本目錄』的意思,所以『./run.sh』代表『執行本目錄下, 名為run.sh的檔案』囉!

参考链接:https://zhidao.baidu.com/question/74975762.html

7、 按行读取文件

1、 head -m filename | tail -1 //查看filename文件的第m行(tail -1 是数字1)

2、 e.g. head -100 data.txt | tail -1 //查看data.txt文件的第100行

3、tail –f filename一直监控某个文件

8、上传和下载linux文件

上传文件只需在shell终端仿真器中输入命令“rz”,即可从弹出的对话框中选择本地磁盘上的文件,利用Zmodem上传到服务器当前路径下。

下载文件只需在shell终端仿真器中输入命令“sz 文件名”,即可利用Zmodem将文件下载到本地某目录下。

原始版本没有rz和sz安装参考

服务器之间拷贝参考链接

9、总结

• Linux的每個檔案中,可分別給予擁有者、群組與其他人三種身份個別的 rwx 權限;

• 群組最有用的功能之一,就是當你在團隊開發資源的時候,且每個帳號都可以有多個群組的支援;

• 利用ls -l顯示的檔案屬性中,第一個欄位是檔案的權限,共有十個位元,第一個位元是檔案類型, 接下來三個為一組共三組,為擁有者、群組、其他人的權限,權限有r,w,x三種;

• 如果檔名之前多一個『 . 』,則代表這個檔案為『隱藏檔』;

• 若需要root的權限時,可以使用 su - 這個指令來切換身份。處理完畢則使用 exit 離開 su 的指令環境。

• 更改檔案的群組支援可用chgrp,修改檔案的擁有者可用chown,修改檔案的權限可用chmod

• chmod修改權限的方法有兩種,分別是符號法與數字法,數字法中r,w,x分數為4,2,1;

• 對檔案來講,權限的效能為:

r:可讀取此一檔案的實際內容,如讀取文字檔的文字內容等;
w:可以編輯、新增或者是修改該檔案的內容(但不含刪除該檔案);
x:該檔案具有可以被系統執行的權限。

• 對目錄來說,權限的效能為:

r (read contents in directory)
w (modify contents of directory)
x (access directory)

• 要開放目錄給任何人瀏覽時,應該至少也要給予r及x的權限,但w權限不可隨便給;

• 能否讀取到某個檔案內容,跟該檔案所在的目錄權限也有關係 (目錄至少需要有 x 的權限)。

• Linux檔名的限制為:單一檔案或目錄的最大容許檔名為 255 個英文字元或 128 個中文字元;

• 根據FHS的官方文件指出, 他們的主要目的是希望讓使用者可以瞭解到已安裝軟體通常放置於那個目錄下

• FHS訂定出來的四種目錄特色為:shareable, unshareable, static, variable等四類;

• FHS所定義的三層主目錄為:/, /var, /usr三層而已;

• 絕對路徑檔名為從根目錄 / 開始寫起,否則都是相對路徑的檔名。

6、创建文件夹和文件

mkdir filename 创建文件夹 touch filename 创建文件

7、移动、复制、删除文件

1、移动文件

mv hello bin/

上述命令将hello文件移动到bin目录下,也可以移动目录。

mv photos/  桌面/

在使用mv进行文件移动时,没有任何提示,那如果出现重复的名称是没有移动成功,还是覆盖了呢,所以我们要在mv命令后加上 -i

mv -i hello bin/

会出现下面的提示

mv:是否覆盖bin/hello?

那么回答y表示覆盖,n表示跳过这个文件。

还有一个-b选项通过在同名的文件后自动加上”~"来避免发生覆盖

mv -b hello bin/

Linux中可以直接使用mv来进行重命名

mv hello test

上述的命令就是将hello文件改为名为test的文件

2、复制文件

cp test study/

将文件test复制到study目录下,和mv命令一样,默认情况下对同名文件执行的是覆盖操作,我们同样可以使用-i和-b来个命令。在使用cp复制整个目录时需要加上-r命令,来实现子目录的完全复制

cp  -r test/ bin/

3、删除文件

rmdir用于删除目录,但是rmdir只能删除空目录,删除一个目录之前,首先要将该目录下的文件和子目录删除,删除文件需要用到rm命令,rm命令可以一次删除一个或者几个文件

$ rm test/*.cpp

删除了test目录下全部的.cpp文件,和上面的cp和mv的情况一下,默认情况下rm操作meiiyou任何提示,我们可以使用-i来进行删除提示:

$ rm -i test/hello

回复y表示删除,n表示跳过该文件,对于只读文件,即便不加上-i选项,rm命令也会对此进行提示。也可以使用-f来避免这样的交互式操作

$ rm -f test/hello

使用-r参数的命令会递归的删除目录下所有的文件和子目录:

$ rm -r test/

4、删除文件和文件夹

使用: rm –rf fiename

5、总结

复制、删除、移动文件

复制:cp filename path
删除: rm filename path
移动:mv filename path
删除文件夹和文件: rm -rf filename
絕對路徑:『一定由根目錄 / 寫起』;相對路徑:『不由 / 寫起,而是由相對當前目錄寫起』
特殊目錄有:., .., -, ~, ~account需要注意;
與目錄相關的指令有:cd, mkdir, rmdir, pwd 等重要指令;
rmdir 僅能刪除空目錄,要刪除非空目錄需使用『 rm -r 』指令;
使用者能使用的指令是依據 PATH 變數所規定的目錄去搜尋的;
ls 可以檢視檔案的屬性,尤其 -d, -a, -l 等選項特別重要!
檔案的複製、刪除、移動可以分別使用:cp, rm , mv等指令來操作;
檢查檔案的內容(讀檔)可使用的指令包括有:cat, tac, nl, more, less, head, tail, od 等
cat -n 與 nl 均可顯示行號,但預設的情況下,空白行會不會編號並不相同;
touch 的目的在修改檔案的時間參數,但亦可用來建立空檔案;
一個檔案記錄的時間參數有三種,分別是 access time(atime), status time (ctime), modification time(mtime),ls 預設顯示的是 mtime。
除了傳統的rwx權限之外,在Ext2/Ext3/Ext4/xfs檔案系統中,還可以使用chattr與lsattr設定及觀察隱藏屬性。 常見的包括只能新增資料的 +a 與完全不能更動檔案的 +i 屬性。
新建檔案/目錄時,新檔案的預設權限使用 umask 來規範。預設目錄完全權限為drwxrwxrwx, 檔案則為-rw-rw-rw-。
檔案具有SUID的特殊權限時,代表當使用者執行此一binary程式時,在執行過程中使用者會暫時具有程式擁有者的權限
目錄具有SGID的特殊權限時,代表使用者在這個目錄底下新建的檔案之群組都會與該目錄的群組名稱相同。
目錄具有SBIT的特殊權限時,代表在該目錄下使用者建立的檔案只有自己與root能夠刪除!
觀察檔案的類型可以使用 file 指令來觀察;
搜尋指令的完整檔名可用 which 或 type ,這兩個指令都是透過 PATH 變數來搜尋檔名;
搜尋檔案的完整檔名可以使用 whereis 找特定目錄或 locate 到資料庫去搜尋,而不實際搜尋檔案系統;
利用 find 可以加入許多選項來直接查詢檔案系統,以獲得自己想要知道的檔名。

8、 磁盘管理

使用df

df命令参数功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息。

语法:

df [参数]

选项与参数:

• -a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;

• -k :以 KBytes 的容量显示各文件系统;

• -m :以 MBytes 的容量显示各文件系统;

• -h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;#易读直接显示大小

• -H :以 M=1000K 取代 M=1024K 的进位方式;#易读直接显示大小

linux基础一篇就够了

• -T :显示文件系统类型, 连同该 partition 的 filesystem 名称 (例如 ext3) 也列出;

• -i :不用硬盘容量,而以 inode 的数量来显示

9、 压缩、打包和解压

1、各样式打包解压

.tar 解包 tar xvf filename.tar

.tar 打包 tar cvf filename.tar dirname(路径或直接文件名)#filename为打包后的文件名

.gz 解压1 gunzip filename.gz

.gz 解压2 gzip -d filename.gz

.gz 压缩 gzip filename(需要压缩的文件名称)

.tar.gz 和 .tgz 解压 tar zxvf filename.tar.gz

.tar.gz 和 .tgz 压缩 tar zcvf filename.tar.gz dirname

.bz2 解压1 bzip2 -d filename.bz2

.bz2 解压2 bunzip2 filename.bz2

.bz2 压缩 bzip2 -z filename

.tar.bz2 解压 tar jxvf filename.tar.bz2

.tar.bz2 压缩 tar jcvf filename.tar.bz2 dirname

.bz 解压1 bzip2 -d filename.bz

.bz 解压2 bunzip2 filename.bz

.tar.bz 解压 tar jxvf filename.tar.bz

.z 解压 uncompress filename.z

.z 压缩 compress filename

.tar.z 解压 tar zxvf filename.tar.z

.tar.z 压缩 tar zcvf filename.tar.z dirname

.zip 解压 unzip filename.zip

.zip 压缩 zip filename.zip dirname

.rar 解压 rar x filename.rar

.rar 压缩 rar a filename.rar dirname

2、总结

• 压缩指令为透过一些运算方法去将原本的档案进行压缩,以减少档案所占用的磁碟容量。压缩后与压缩前的档案所占用的磁碟容量比值, 就可以被称为是『压缩比』

• 压缩的好处是可以减少磁碟容量的浪费,在WWW 网站也可以利用档案压缩的技术来进行资料的传送,好让网站频宽的可利用率上升喔

• 压缩档案的副档名大多是:『*.gz, *.bz2, *.xz, *.tar, *.tar.gz, *.tar.bz2, *.tar.xz』

• 常见的压缩指令有gzip, bzip2, xz。压缩率最佳的是xz,若可以不计时间成本,建议使用xz 进行压缩。

• tar 可以用来进行档案打包,并可支援gzip, bzip2, xz 的压缩。

• 压缩:tar -Jcv -f filename.tar.xz 要被压缩的档案或目录名称

• 查询:tar -Jtv -f filename.tar.xz

• 解压缩:tar -Jxv -f filename.tar.xz -C 欲解压缩的目录

• xfsdump 指令可备份档案系统或单一目录

• xfsdump 的备份若针对档案系统时,可进行0-9 的level 差异备份!其中level 0 为完整备份;

• xfsrestore 指令可还原被xfsdump 建置的备份档;

• 要建立光碟烧录资料时,可透过mkisofs 指令来建置;

• 可透过wodim 来写入CD 或DVD 烧录机

• dd 可备份完整的partition 或disk ,因为dd 可读取磁碟的sector 表面资料

• cpio 为相当优秀的备份指令,不过必须要搭配类似find 指令来读入欲备份的档名资料,方可进行备份动作。

vim和vi

Linux系统上面都有各种文书编辑器,常见Linux 上面的指令都预设使用vi 作为资料编辑的介面,一定要学会 vi (通用型)

可以将vim视作vi的进阶版本,vim可以用颜色或底线等方式来显示一些特殊的资讯。

vi的使用

基本上vi共分为三种模式:

一般指令模式(command mode)

以vi 打开一个档案就直接进入一般指令模式了(这是预设的模式,也简称为一般模式)。可以使用『上下左右』按键来移动游标,你可以使用『删除字元』或『删除整列』来处理档案内容, 也可以使用『复制、贴上』来处理你的文件资料。

示例:

vi a.txt

编辑模式(insert mode)

在一般指令模式中按下『i, I, o, O, a, A, r, R』等任何一个字母之后才会进入编辑模式。按下这些按键时,在画面的左下方会出现『INSERT或REPLACE』的字样,此时才可以进行编辑。而如果要回到一般指令模式时,按下『Esc』这个按键即可退出编辑模式。

示例:

linux基础一篇就够了

『i, I, o, O, a, A, r, R』等任何一个字母之后才会进入编辑模式

指令列命令模式(command-line mode)

在一般模式当中,输入『 : / ?』三个中的任何一个按钮,就可以将游标移动到最底下那一列。

示例:

:q(未修改退出)
:wq(保存并退出)
:q!(修改后不需要保存强制退出)
?name(查找name,大小写(N,n)查找下一个)

常用命令

向上翻页 PgUp
向下翻页 PgDn
光标移动到首页行首 gg
光标移动到尾页最后一行行首 shift+g 或 G
:行数(跳到该行)
删除一整行 dd

详细示意图:

linux基础一篇就够了

总结

Linux 底下的设定档多为文字档,故使用vim 即可进行设定编辑;
vim 可视为程式编辑器,可用以编辑shell script, 设定档等,避免打错字;
vi 为所有unix like 的作业系统都会存在的编辑器,且执行速度快速;
vi 有三种模式,一般指令模式可变换到编辑与指令列模式,但编辑模式与指令列模式不能互换;
常用的按键有i, [Esc], :wq 等;
vi 的画面大略可分为两部份,(1)上半部的本文与(2)最后一行的状态+指令列模式;
数字是有意义的,用来说明重复进行几次动作的意思,如5yy 为复制5 列之意;
游标的移动中,大写的G 经常使用,尤其是1G, G 移动到文章的头/尾功能!
vi 的取代功能也很棒!:n1,n2s/old/new/g 要特别注意学习起来;
小数点『 . 』为重复进行前一次动作,也是经常使用的按键功能!
进入编辑模式几乎只要记住: i, o, R 三个按钮即可!尤其是新增一列的o 与取代的 R
vim 会主动的建立swap 暂存档,所以不要随意断线!
如果在文章内有对齐的区块,可以使用[ctrl]-v 进行复制/贴上/删除的行为
使用:sp 功能可以分割视窗
若使用vim 来撰写网页,若需要CSS 元素资料,可透过[ctrl]+x, [ctrl]+o 这两个连续组合按键来取得关键字
vim 的环境设定可以写入在~/.vimrc 档案中;
可以使用iconv 进行档案语系编码的转换
使用dos2unix 及unix2dos 可以变更档案每一列的行尾断行字元。

BASH

BASH 是系统中其中一个shell。

硬体、核心与使用者的相关性图示

linux基础一篇就够了

查看bash说明:

man bash

查看某个命令是否为bash 所提供的内建指令

范例一:查询一下ls这个指令是否为bash内建?
[dmtsai@study ~]$ type ls
ls is aliased to `ls --color=auto' <==未加任何参数,列出ls的最主要使用情况
[dmtsai@study ~]$ type -t ls
alias < ==仅列出ls执行时的依据
[dmtsai@study ~]$ type -a ls
ls is aliased to `ls --color=auto' <==最先使用aliase
ls is /usr/bin/ls <= =还有找到外部指令在/bin/ls 范例二:那么cd呢?
[dmtsai@study ~]$ type cd
cd is a shell builtin <==看到了吗?cd是shell内建指令

透过type这个指令我们可以知道每个指令是否为bash的内建指令。

某些时候当填写的路径较长时可使用“"换行按下\按enter不会执行命令只会换行

快速删除长命令

[ctrl]+u/[ctrl]+k 分别是从游标处向前删除指令串([ctrl]+u) 及向后删除指令串([ctrl]+k)。

[ctrl]+a/[ctrl]+e 分别是让游标移动到整个指令串的最前面([ctrl]+a) 或最后面([ctrl]+e)。

Shell 的变数(变量)功能

什么是『变数』呢?简单的说,就是让某一个特定字串代表不固定的内容就是了。举个大家在国中都会学到的数学例子,那就是:『 y = ax + b 』这东西,在等号左边的(y)就是变数,在等号右边的(ax+b)就是变数内容。要注意的是,左边是未知数,右边是已知数!

变数示意图:

linux基础一篇就够了

程式、变数与不同使用者的关系
注意大小写,小写的mail 是指令, 大写的MAIL 则是变数名称

[admin@ ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/admin/.local/bin:/home/admin/bin
如上如果小写不会出现相应的结果

变数的取用就如同上面的范例,利用echo 就能够读出,只是需要在变数名称前面加上$ , 或者是以${变数} 的方式来取用都可以!

例题:
请在萤幕上面显示出您的环境变数HOME 与MAIL:
答:
echo $HOME或者是echo ${HOME}
echo $MAIL或者是echo ${MAIL}

类似编程python中的

a=b+c+d
.....
f=a+n
多处调用a时只需要将第一个a改变就可

应用场景

例如你要写一个大型的script 时,有些资料因为可能由于使用者习惯的不同而有差异,比如说路径好了,由于该路径在script 被使用在相当多的地方,如果下次换了一部主机,都要修改script 里面的所有路径,那么我一定会疯掉!这个时候如果使用变数,而将该变数的定义写在最前面,后面相关的路径名称都以变数来取代, 嘿嘿!那么你只要修改一行就等于修改整篇script 了!方便的很!所以,良好的程式设计师都会善用变数的定义!

示意图:

linux基础一篇就够了

设定变数

『设定』或者是『修改』 某个变数的内容啊?很简单啦!用『等号(=)』连接变数与他的内容就好啦!举例来说: 我要将myname 这个变数名称的内容设定为VBird ,那么:

[dmtsai@study ~]$ echo ${myname}
<==这里并没有任何资料~因为这个变数尚未被设定!是空的!
[dmtsai@study ~]$ myname=VBird
[dmtsai@study ~]$ echo ${myname}
VBird <==出现了!因为这个变数已经被设定了!

变数的设定规则

变数与变数内容以一个等号『=』来连结,如下所示:

『myname=VBird』

等号两边不能直接接空白字元,如下所示为错误:

『myname = VBird』或『myname=VBird Tsai』

变数名称只能是英文字母与数字,但是开头字元不能是数字,如下为错误:

『2myname=VBird』

变数内容若有空白字元可使用双引号『"』或单引号『’』将变数内容结合起来,但

双引号内的特殊字元如$等,可以保有原本的特性,如下所示:

『var="lang is $LANG"』则『echo $var』可得『lang is zh_TW.UTF-8』

单引号内的特殊字元则仅为一般字元(纯文字),如下所示:

『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』

可用跳脱字元『 \ 』将特殊符号(如[Enter], $, ,空白字元, '等)变成一般字元,如:

『myname=VBird\ Tsai』

在一串指令的执行中,还需要藉由其他额外的指令所提供的资讯时,可以使用反单引号『指令』或『$(指令)』。特别注意,那个`是键盘上方的数字键1左边那个按键,而不是单引号!例如想要取得核心版本的设定:

『version=$(uname -r)』再『echo $version』可得『3.10.0-229.el7.x86_64』

若该变数为扩增变数内容时,则可用"$变数名称"或${变数}累加内容,如下所示:

『PATH="$PATH":/home/bin』或『PATH=${PATH} :/home/bin』

若该变数需要在其他子程序执行,则需要以export来使变数变成环境变数:

『export PATH』

通常大写字元为系统预设变数,自行设定变数可以使用小写字元,方便判断(纯粹依照使用者兴趣与嗜好) ;

取消变数的方法为使用unset:『unset变数名称』例如取消myname的设定:

『unset myname』

示例:

范例一:设定一变数name ,且内容为VBird
[dmtsai@study ~]$ 12name=VBird
bash: 12name=VBird: command not found... <==萤幕会显示错误!因为不能以数字开头!
[dmtsai@study ~]$ name = VBird <==还是错误!因为有空白!
[dmtsai@study ~]$ name=VBird <==OK的啦! 范例二:承上题,若变数内容为VBird's name呢,就是变数内容含有特殊符号时:
[dmtsai@study ~]$ name=VBird's name
# 单引号与双引号必须要成对,在上面的设定中仅有一个单引号,因此当你按下enter后,
# 你还可以继续输入变数内容。这与我们所需要的功能不同,失败啦!
#记得,失败后要复原请按下[ctrl]-c结束!
[dmtsai@study ~]$ name="VBird's name" <==OK的啦!
#指令是由左边向右找→,先遇到的引号先有用,因此如上所示,单引号变成一般字元!
[dmtsai@study ~]$ name='VBird's name' <==失败的啦!
#因为前两个单引号已成对,后面就多了一个不成对的单引号了!因此也就失败了!
[dmtsai@study ~]$ name=VBird\'s\ name <==OK的啦!
#利用反斜线(\)跳脱特殊字元,例如单引号与空白键,这也是OK的啦! 范例三:我要在PATH这个变数当中『累加』:/home/dmtsai/bin这个目录
[dmtsai@study ~]$ PATH=$PATH:/home/dmtsai/bin
[dmtsai@study ~]$ PATH=" $PATH":/home/dmtsai/bin
[dmtsai@study ~]$ PATH=${PATH}:/home/dmtsai/bin
#上面这三种格式在PATH里头的设定都是OK的!但是底下的例子就不见得啰! 范例四:承范例三,我要将name的内容多出"yes"呢?
[dmtsai@study ~]$ name=$nameyes
#知道了吧?如果没有双引号,那么变数成了啥?name的内容是$nameyes这个变数!
#呵呵!我们可没有设定过nameyes这个变数呐!所以,应该是底下这样才对!
[dmtsai@study ~]$ name="$name"yes
[dmtsai@study ~]$ name=${name}yes <==以此例较佳! 范例五:如何让我刚刚设定的name=VBird可以用在下个shell的程序?
[dmtsai@study ~]$ name=VBird
[dmtsai@study ~]$ bash <==进入到所谓的子程序
[dmtsai@study ~]$ echo $name <==子程序:再次的echo一下;
<= =嘿嘿!并没有刚刚设定的内容喔!
[dmtsai@study ~]$ exit <==子程序:离开这个子程序
[dmtsai@study ~]$ export name
[dmtsai@study ~]$ bash <==进入到所谓的子程序
[dmtsai@study ~]$ echo $name <==子程序:在此执行!
VBird <==看吧!出现设定值了!
[dmtsai@study ~]$ exit <==子程序:离开这个子程序

取消变数

范例七:取消刚刚设定的name这个变数内容
[dmtsai@study ~]$ unset name

快速访问多重目录

如我们现在有一个常用目录:cluster/server/work/*_2015/003/

在一般的情况下,如果你想要进入上述的目录得要『cd /cluster/server/work/*_2015/003/』, 但如此一来变换目录就很麻烦。此时,利用底下的方式来降低指令下达错误的问题:

[dmtsai@study ~] work="/cluster/server/work/*_2015/003/"
[dmtsai@study ~] cd $work
常访问的目录我们可以设置成变数,这样可以快速访问

环境变数的功能

查看目前我的shell 环境中, 有多少预设的环境变数,可以利用两个指令来查阅,分别是env 与export !

结果示例:

范例一:列出目前的shell环境下的所有环境变数与其内容。
[dmtsai@study ~]$ env
HOSTNAME=study.centos.vbird <==这部主机的主机名称
TERM=xterm <==这个终端机使用的环境是什么类型
SHELL=/bin/bash <==目前这个环境下,使用的Shell是哪一个程式?
HISTSIZE=1000 <== 『记录指令的笔数』在CentOS预设可记录1000笔
OLDPWD=/home/dmtsai <==上一个工作目录的所在
LC_ALL=en_US.utf8 <==由于语系的关系,鸟哥偷偷丢上来的一个设定
USER=dmtsai <==使用者的名称啊!
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd= 40;33;01:
or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st= 37;44:ex=01;32:
*.tar=01... <==一些颜色显示
MAIL=/var/spool/mail/dmtsai <==这个使用者所取用的mailbox位置
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
PWD=/home/dmtsai <==目前使用者所在的工作目录(利用pwd取出!)
LANG=zh_TW.UTF-8 <==这个与语系有关,底下会再介绍!
HOME=/home/dmtsai <==这个使用者的家目录啊!
LOGNAME=dmtsai <==登入者用来登入的帐号名称
_=/usr/bin/env <==上一次使用的指令的最后一个参数(或指令本身)

变数内容的删除、取代与替换(Optional)

删除示例:

范例一:先让小写的path自订变数设定的与PATH内容相同

[dmtsai@study ~]$ path=${PATH} //把变数PATH赋值给path
[dmtsai@study ~]$ echo ${path} //获取path变数的内容
/usr/local/bin: / usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

范例二:假设我不喜欢local/bin,所以要将前1个目录删除掉,如何显示?

[dmtsai@study ~]$ echo ${path#/*local/bin:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
分析命令 ${path#/*local/bin:}:
1、特殊字体部分是关键字!用在这种删除模式所必须存在的
2、path是变数名称
3、# 这是重点!代表『从变数内容的最前面开始向右删除』,且仅删除最短的那个
4、/*local/bin: 代表要被删除的部分,由于#代表由前面开始删除,所以这里便由开始的/写起。需要注意的是,我们还可以透过万用字元* 来取代0 到无穷多个任意字元

范例二的结果, path这个变数被删除的内容如下所示:

/usr/local/bin: /usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/. local/bin:/home/dmtsai/bin

范例三:我想要删除前面所有的目录,仅保留最后一个目录

[dmtsai@study ~]$ echo ${path#/*:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 由于一个# 仅删除掉最短的那个,因此他删除的情况可以用底下的删除线来看:
# /usr/local/bin: /usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[dmtsai@study ~]$ echo ${path##/*:}
/home/dmtsai/bin
# 嘿!多加了一个# 变成## 之后,他变成『删除掉最长的那个资料』!亦即是:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin: /home/dmtsai/bin

范例三的结果, path这个变数被删除的内容如下所示:

/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/. local/bin:/home/dmtsai/bin

# :符合取代文字的『最短的』那一个

##:符合取代文字的『最长的』那一个

替换变数

範例一:測試一下是否存在 username 這個變數,若不存在則給予 username 內容為 root

[dmtsai@study ~]$ echo ${username}
<==由於出現空白,所以 username 可能不存在,也可能是空字串
[dmtsai@study ~]$ username=${username-root} //将username的变数内容替换为root
[dmtsai@study ~]$ echo ${username}
root <==因為 username 沒有設定,所以主動給予名為 root 的內容。
[dmtsai@study ~]$ username="vbird tsai" <==主動設定 username 的內容
[dmtsai@study ~]$ username=${username-root} //将username的变数内容替换为root
[dmtsai@study ~]$ echo ${username}
vbird tsai <==因為 username 已經設定了,所以使用舊有的設定而不以 root 取代

若为空内容执行后会自动替换不为空不会替换

命令设置別名: alias, unalias

设置示例:

[admin@localhost ~]$ alias lm='ls -al | more'
[admin@localhost ~]$ lm
total 56
drwx------. 10 admin admin 260 Feb 19 21:46 .
drwxr-xr-x. 6 root root 55 Feb 7 17:58 ..
-rw-rw-r--. 1 admin admin 54 Feb 19 21:46 a.txt
-rw-r--r--. 1 admin admin 12288 Feb 19 21:54 .a.txt.swp
分析:ls -al | more命令本是查看所有文档,但是觉得命令太长不方便,使用alias设置别名就可以直接使用别名lm来访问ls -al | more命令了

取消别名:

[admin@localhost ~]$ unalias lm

Shell 脚本(shell script)

下方为整体总结

简单示例:

#!/bin/bash
echo "Hello World !"

分析: #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。

echo 命令用于向窗口输出文本(类似编程的print())。

vi test.sh //创建并打开 test.sh文件
插入脚本内容,如上面的示例代码
保存并退出
chmod +x ./test.sh #使脚本具有执行权限 或使用chmod 777 test.sh
./test.sh #执行est.sh脚本

执行步骤图:

linux基础一篇就够了

shell变量

变量规则

命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。

使用变量

使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

[admin@ ~]$ your_name="qinjx"
[admin@ ~]$ echo $your_name //方法一
qinjx
[admin@ ~]$ echo ${your_name} //方法二
qinjx

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

推荐给所有变量加上花括号

已定义的变量可重复定义:

[admin@ ~]$ your_name="tom"  //第一次定义
[admin@ ~]$ echo $your_name //查看结果
tom
[admin@ ~]$ your_name="alibaba" //第二次定义
[admin@ ~]$ echo $your_name //查看结果
alibaba
第二次赋值的时候不能写$your_name="alibaba",使用变量的时候才加美元符($)。

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

#!/bin/bash
myUrl="http://www.baidu.com"
readonly myUrl
myUrl="http://www.taobao.com"
运行脚本,结果如下:
./test.sh: line 4: myUrl: readonly variable

删除变量

使用 unset 命令可以删除变量。语法:

[admin@ ~]$ unset variable_name

变量被删除后不能再次使用。unset 命令不能删除只读变量.

变量类型

运行shell时,会同时存在三种变量:

  1. 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  2. 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

Shell 字符串

字符串是shell编程中最常用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。

单引号

str='this is a string'

单引号字符串的限制:

单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;

单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

双引号

your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"

双引号的优点:

双引号里可以有变量

双引号里可以出现转义字符

拼接字符串

your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

获取字符串长度

使用#显示长度
string="abcd"
echo ${#string} #输出 4

提取子字符串

以下实例从字符串第 2 个字符开始截取 4 个字符:

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

查找子字符串

查找字符 "i 或 s" 的位置:
string="runoob is a great company"
echo `expr index "$string" is` # 输出 8

注意: 以上脚本中 “`” 是反引号,而不是单引号 “’”。

Shell 数组

1、bash支持一维数组(不支持多维数组),并且没有限定数组的大小

2、数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

定义数组

在Shell中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 … 值n)

例如:

array_name=(value0 value1 value2 value3)

或者

array_name=(

value0

value1

value2

value3)

还可以单独定义数组的各个分量:

array_name[0]=value0

array_name[1]=value1

array_name[n]=valuen

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

${array_name[index]}

实例

#!/bin/bash
# author:w my_array=(A B "C" D) echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"

执行结果:

[admin@ bin]$ chmod +x test.sh //赋予所有者执行权限
[admin@ bin]$ ./test.sh //执行
第一个元素为: A
第二个元素为: B
第三个元素为: C
第四个元素为: D

获取数组中的所有元素

使用@ 或 * 可以获取数组中的所有元素,例如:

#!/bin/bash
# author:w
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"

执行脚本,输出结果如下所示:

[admin@ bin]$ chmod +x test.sh //赋予所有者执行权限
[admin@ bin]$ ./test.sh //执行
数组的元素为: A B C D
数组的元素为: A B C D

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,使用# ,例如:

#!/bin/bash
# author:w
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D
echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"

执行脚本,输出结果如下所示:

[admin@ bin]$ chmod +x test.sh //赋予所有者执行权限
[admin@ bin]$ ./test.sh //执行
数组元素个数为: 4
数组元素个数为: 4

shell运算符(±*/)

Shell 和其他编程语言一样,支持多种运算符,包括:

算数运算符

关系运算符

布尔运算符

字符串运算符

文件测试运算符

两个数相加(注意使用的是反引号 ` 而不是单引号 '):

#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
输出结果:两数之和为 : 4

注:

1、表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
2、完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

下表所有¥符号代表$符号

假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
+ 加法 `expr ¥a + ¥b` 结果为 30。
- 减法 `expr ¥a - ¥b` 结果为 -10。
* 乘法 `expr ¥a \* ¥b` 结果为 200。
/ 除法 `expr ¥b / ¥a` 结果为 2。
% 取余 `expr ¥b % ¥a` 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。

注意: 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。

算术运算符实例如下:

#!/bin/bash
# author:w
a=10 //设置变量不能空格
b=20
val=`expr $a + $b` //运算必须空格隔开
echo "a + b : $val"
输出结果:a + b : 30
val=`expr $a - $b`
echo "a - b : $val"
输出结果:a - b : -10
val=`expr $a \* $b`
echo "a * b : $val"
输出结果:a * b : 200
val=`expr $b / $a`
echo "b / a : $val"
输出结果:b / a : 2
val=`expr $b % $a`
echo "b % a : $val"
输出结果:b % a : 0
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi 输出结果:a 不等于 b

注:

乘号(*)前边必须加反斜杠(\)才能实现乘法运算;

if…then…fi 是条件语句。

在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 “*” 不需要转义符号 “” 。

关系运算符(判断=!=><)

下表所有¥符号代表$符号

假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ ¥a -eq ¥b ] 返回 false。
-ne 检测两个数是否相等,不相等返回 true。 [ ¥a -ne ¥b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ ¥a -gt ¥b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ ¥a -lt ¥b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ ¥a -ge ¥b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ ¥a -le ¥b ] 返回 true。

实例

关系运算符实例如下:

#!/bin/bash
# author:w
a=10
b=20 if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi

执行结果:

10 -eq 20: a 不等于 b
10 -ne 20: a 不等于 b
10 -gt 20: a 不大于 b
10 -lt 20: a 小于 b
10 -ge 20: a 小于 b
10 -le 20: a 小于或等于 b

布尔运算符(TrueFalse)

下表所有¥符号代表$符号

假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ ¥a -lt 20 -o ¥b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ ¥a -lt 20 -a ¥b -gt 100 ] 返回 false。

实例

布尔运算符实例如下:

#!/bin/bash
# author:w
a=10
b=20 if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi

执行结果:

10 != 20 : a 不等于 b
10 小于 100 且 20 大于 15 : 返回 true
10 小于 100 或 20 大于 100 : 返回 true
10 小于 5 或 20 大于 100 : 返回 false

逻辑运算符(and or)

假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

实例

逻辑运算符实例如下:

#!/bin/bash
# author:w
a=10
b=20 if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi

执行结果:

返回 false
返回 true

字符串运算符(判断字符串)

假定变量 a 为 “abc”,变量 b 为 “efg”:

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否为0,不为0返回 true。 [ -n $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

实例

字符串运算符实例如下:

#!/bin/bash
# author:w
a="abc"
b="efg" if [ $a = $b ]
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n $a ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi

执行结果:

abc = efg: a 不等于 b
abc != efg : a 不等于 b
-z abc : 字符串长度不为 0
-n abc : 字符串长度不为 0
abc : 字符串不为空

文件测试运算符(判断文件是否存在、为空)

常用判断文件方法

用于检测 Linux文件的各种属性

以下为常用的两个

运算符 说明 举例
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-f file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -f $file ] 返回 true。

实例

判断文件是否存在

假设 /home/admin/bin/下有一个叫hello.sh的文件

#!/bin/bash
filename=" /home/admin/bin/hello.sh"
if [ -f $filename ]
then
echo "文件存在"
else
echo "文件不存在"
fi

执行结果:

文件存在

判断文件是否存在,是否为空

假设 /home/admin/bin/下有一个叫hello.sh的文件且不为空

#!/bin/bash
filename=" /home/admin/bin/hello.sh"
if [ -f $filename ]
then
echo "文件存在"
else
echo "文件不存在"
fi
if [ -s $filename ]
then
echo "文件不为空"
else
echo "文件为空"
fi

执行结果:

文件存在
文件不为空

echo命令

如需保留某些符号如: " ` \ 等在前面加一个 \(转义符)

echo为输出命令(类似python中的print())

接收用户键盘输入

使用read -p(类似python中的input())

实例:

执行[admin@ bin]$ touch hello.sh;chmod +x hello.sh;vi hello.sh
输入如下内容:
#!/bin/sh
count=0 #变量不能有空格,其他大部分地方必须有空格
while ((1))#死循环
read -p "请选择你要使用的计算器:1、加法 2、减法 3、退出" number #接收用户输入(类似python中的input())
echo "共使用$count次`date`" >> ~/a.sh #将使用次数和时间存储到家目录的a.sh如果没有会自动创建
if [ $number = 1 ]
then
echo "你输入的是$number,加法"
read -p "请输入第一个数" one
read -p "请输入第二个数" two
let sum=one+two #sum前面加了let这个变量就会自动计算不加不会计算
echo "结果是"$sum
fi if [ $number = 2 ]
then
echo "你输入的是$number,减法"
read -p "请输入第一个数" one1
read -p "请输入第二个数" two1
let reduce=one1-two1
echo "结果是"$reduce
fi
....
#注意:shell中的乘法写法是1\*1 不是1*1 if [ $number = 3 ]
then
echo "你输入的是$number,退出"
break #跳出循环
fi
done
#以上代码接收用户输入并判断用户需要的计算方式
#以上为计算器简单构思练习

执行结果:

[admin@ bin]$ ./hello.sh
请选择你要使用的计算器:1
你输入的是1,加法

显示结果换行与不换行

换行:

echo -e "OK! \n" # -e 开启转义
echo "It it a test"

注:echo会默认换行(\n)printf不会

输出结果:

OK!
It it a test

不换行:

#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"

执行结果:

OK! It is a test

将结果输出到某一文件

[admin@ bin]$ echo "It is a test" > myfile

实例:

将文件结果输出到b

如:

1、在a.sh 写入命令echo “It is a test” > ~/b.sh

2、执行a.sh文件(此操作会覆盖b.sh的内容)

3、打开b.sh里面就能看到It is a test了

不会覆盖使用>>

echo "使用第$count次`date`" >> ~/a.sh #`date`时显示当前时间

常用方法:

命令 说明 分析
command > file 将输出重定向到 file。 输出到文件(会覆盖)
command < file 将输入重定向到 file。 输出到文件(会覆盖)
command >> file 将输出以追加的方式重定向到 file。 输出到文件(不会覆盖)

让结果显示日期

echo "It is a test" > ~/a.txt
echo "执行成功 "`date`

注意date这里使用的是反引号 `, 而不是单引号 '。

执行结果:

[admin@ bin]$ ./b.sh
执行成功 Fri Feb 23 16:58:49 CST 2018

Shell printf 命令

printf类似echo有以下几点区别:

1、printf 的脚本比使用 echo 移植性好。
2、printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。
3、默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n。

实例:

[admin@ bin]$ echo "Hello, Shell"
Hello, Shell
[admin@ bin]$ printf "Hello, Shell\n"
Hello, Shell

用一个脚本来体现printf的强大功能:

#!/bin/bash
# author:w
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

执行结果:

姓名     性别   体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99

分析:

1、%s %c %d %f都是格式替代符

2、%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

3、%-4.2f 指格式化为小数,其中.2指保留2位小数。

%d %s %c %f 格式替代符详解:

d: Decimal 十进制整数 – 对应位置参数必须是十进制整数,否则报错!

s: String 字符串 – 对应位置参数必须是字符串或者字符型,否则报错!

c: Char 字符 – 对应位置参数必须是字符串或者字符型,否则报错!

f: Float 浮点 – 对应位置参数必须是数字型,否则报错!

如:其中最后一个参数是 “def”,%c 自动截取字符串的第一个字符作为结果输出。

printf "%d %s %c\n" 1 "abc" "def"
结果:1 abc d

更多实例:

#!/bin/bash
# format-string为双引号
printf "%d %s\n" 1 "abc" # 单引号与双引号效果一样
printf '%d %s\n' 1 "abc" # 没有引号也可以输出
printf %s abcdef

执行结果:

1 abc
1 abc
abcdef

printf转义符

序列 说明
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符

判断循环(if、for、while)

if else

if else 语法格式:

if condition(循环条件)
then
command1
command2
...
commandN
else
command
fi

if else-if else

if else-if else 语法格式:

if condition1
then
command1
elif condition2
then
command2
else
commandN
fi

实例:

a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ] //-gt判断是不是左侧大返回True
then
echo "a 大于 b"
elif [ $a -lt $b ] //-lt判断是不是右侧大返回True
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi

输出结果:

a 小于 b

for 循环

与其他编程语言类似,Shell支持for循环。

for循环一般格式为:

for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

写成一行:

for var in item1 item2 ... itemN; do command1; command2… done;

实例:

循环输出1到100

#!第一种写法 类似C、Java
for ((i=1; i<=100; i ++))
do
echo $i
done
#!第二种写法 in应用
for i in {1..100}
do
echo $i
done

#!/bin/bash
for i in {1..100}
do
printf "The value is: $i\n"
done #!第三种写法 seq 使用
for i in `seq 1 100`
do
echo $i
done

来100个不同的名字:

#!/bin/bash
for ((i=1;i<=100;i++))
do
printf "a$i\n"
done 结果:a1 a2 a3.....

while 循环

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while condition
do
command
done

实例:

以下是一个while循环,如果int小于等于5,那么条件返回真。int从0开始,每次循环处理时,int加1。运行上述脚本,返回数字1到5,然后终止。

#!/bin/sh
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

运行脚本,输出:

1
2
3
4
5

分析:

使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量

let arg(要执行的表达式)

示例:

one=2 #变量不能有空格,其他大部分地方必须有空格
two=2
let sum=one+two
echo "结果是"$sum -->4 #sum前面加了let这个变量就会自动计算不加不会计算

无限循环(死循环)

无限循环语法格式:

while :
do
command
done
或者
while true
do
command
done
或者
while ((1))
do
command
done
或者
for (( ; ; ))
....

case(检测匹配)

跟if其很像

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

示例1:

下面的脚本提示输入1到4,与每一种模式进行匹配:

cho '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
#当输入后会自动判断输入是否在范围内

示例2:

#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done

执行结果:

输入 1 到 5 之间的数字:3
你输入的数字为 3!
输入 1 到 5 之间的数字:7
你输入的数字不是 1 到 5 之间的! 游戏结束

跳出循环

break

break结束循环(只能跳出一层如果多个需要再添加break)

实例:

while ((1)) #死循环
read -p "请输入一个数字:" number #接收键盘输入
if [ $number = 5 ]
then
echo "你输入的是$number,退出"
break #如果number=5就跳出循环
fi

continue

continue结束本次循环继续下次循环

while ((1)) #死循环
read -p "请输入一个数字:" number #接收键盘输入
if [ $number = 5 ]
then
echo "你输入的是$number,退出"
continue #如果number=5继续继续提示请输入一个数字不会像break结束循环
fi

shell函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

示例:

#!/bin/bash
# author:w
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun #类似python但调用时函数名称不需要在后面加一个()
echo "-----函数执行完毕-----"

执行结果:

-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----

定义一个带有return语句的函数:

示例:

#!/bin/sh

func1()
{
read -p "请输入第一个数" one
read -p "请输入第二个数" two
let sum=one+two
return $sum
} func1
echo "计算的结果是:$?" # $? 执行上一个指令的返回值

执行结果:

[admin@localhost bin]$ ./hello.sh
请输入第一个数2
请输入第二个数2
计算的结果是:4

函数参数

调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…

示例:

#!/bin/bash

funWithParam(){
echo "第一个参数为 $1 !" #调用时跟的参数函数内会自动按位置输出
echo "第二个参数为 $2 !" #1-9写$1 $2 $3.....
echo "第二个参数为 $9 !"
echo "第十个参数为 ${10} !" #10以上按这种写 ${10} ${11}.....
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 10 34 73 #调用时直接在后面跟需要传的参数

执行结果:

第一个参数为 1 !
第二个参数为 2 !
第二个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 10 34 73 !

脚本相互调用

格式:

. filename   # 注意点号(.)和文件名中间有一空格

或

source filename

实例

创建两个 shell 脚本文件。

a.sh 代码如下:

url="http://www.baidu.com"

b.sh 代码如下:

#!/bin/bash
. ./c.sh #使用 . 号来引用a.sh 文件
echo "百度官网地址:$url"

给b.sh添加执行权限(a.sh不需要添加就可以)

执行结果:

百度官网地址:http://www.baidu.com

shell debug(调试)

我们可以使用:sh -n filename 查看是否存在语法错误

示例:

echo 菜鸟教程官网地址:$url" #echo后面的字符串少了一个"

执行结果:

[admin@localhost bin]$ sh -n d.sh
d.sh: line 6: unexpected EOF while looking for matching `"'
d.sh: line 7: syntax error: unexpected end of file
提示缺少"符号