《linux命令行與shell編程大全》--讀書筆記

1.初識Linux shell

linux
圖片連接html


2.走進shell

1.進入命令行,CLI(command line interface),也叫Linux控制檯

  • 經過Linux控制檯終端訪問CLI
  • Ctrl+Alt+F1~F7
    注:tty:teletypewriter,指一臺用於發送消息的機器
    控制檯的外觀設置命令:setterm

2.經過圖形化的終端訪問CLI


3.基本的bash shell命令

1. bash手冊

1.1 熟悉DESCRIPTION部分的前兩段能夠學到不少技術行話
1.2 空格鍵:翻頁
1.3 回車鍵:逐行查看node

2. Linux手冊頁的內容區域

  • 1.可執行文件或shell命令
  • 2.系統調用
  • 3.庫調用
  • 4.特殊文件
  • 5.文格式約定
  • 6.遊戲
  • 7.概覽、約定及雜項
  • 8.超級用戶和系統管理員命令
  • 9.內核例程
  • 查看所需的頁面:man section# topic
  • 查看內容簡介:man 1 intro
  • 另外一個參考信息:info info

3.Linux文件系統

3.1 常見的目錄名稱
  • / :虛擬目錄的根目錄
  • /bin :二進制目錄,存放許多用戶級的GNU工具
  • /boot:啓動目錄,存放啓動文件
  • /dev :設備目錄,Linux在這裏建立設備節點
  • /etc :系統配置文件目錄
  • /home:主目錄,Linux在這裏建立用戶目錄
  • /lib :庫目錄,存放系統和應用程序的庫文件
  • /media:媒體目錄,可移動媒體設備的經常使用掛載點
  • /mnt :掛載目錄,另外一個可移動媒體設備的經常使用掛載點
  • /opt :可選目錄,經常使用於存放第三方軟件包和數據文件
  • /proc:進程目錄,存放現有硬件及當前進程的相關信息
  • /root:root用戶的主目錄
  • /sbin:系統二進制目錄,存放許多GNU管理員級工具
  • /run :運行目錄,存放系統運做時的運行時數據
  • /srv :服務目錄,存放本地服務的相關文件
  • /sys :系統目錄,存放系統硬件信息的相關文件
  • /tmp :臨時目錄,能夠在該目錄中建立和刪除臨時工做文件
  • /usr :用戶二進制目錄,大量用戶級的GNU工具和數據文件都存儲在這裏
  • /var :可變目錄,用以存放常常變化的文件,好比日誌文件
3.2 文件和目錄列表
  • ls -F :區分文件和目錄
  • ls -a :顯示隱藏目錄
  • ls -F -R :遞歸列出當前目錄下包含的子目錄中的文件
  • ls -l :長列表格式輸出,每行都包含了下述信息
     文件類型,好比目錄( d )、文件( - )、字符型文件( c )或塊設備( b );
     文件的權限(參見第6章);
     文件的硬連接總數;
     文件屬主的用戶名;
     文件屬組的組名;
     文件的大小(以字節爲單位);
     文件的上次修改時間;
     文件名或目錄名;
3.3 使用元字符通配符過濾文件
  • ls -l scr[ai]pt :a或i
  • ls -l f[a-i]ll :指定字符範圍
  • ls -l f[!a]ll :除了a
3.4 建立文件
  • touch test_one :建立一個空文件,若是已經存在,則修改文件的建立時間
  • touch -a test_one :改變文件建立時間
  • ls -l –time=atime test_one :加粗文件建立時間
3.5 連接文件:指向文件真實位置的佔位符
3.5.1 符號連接:指向虛擬結構目錄中某個地方的另外一個文件,彼此內容不一樣
  • ln -s data_file s1_data_file :給data_file建立一個符號連接
  • ls -l *data_file :查看該連接文件,能夠看到大小不同
  • ls -i *data_file :查看兩個文件的inode節點編號,能夠看到不同
3.5.2硬連接:會建立獨立的虛擬文件,包含原始文件的信息和位置,本質上是同一個文件(必須在同一個媒體)
  • ln code_file h1_code_file :建立一個硬連接
  • ls -li *code_file :查看兩個文件
3.6.刪除文件
  • rm -i fall :帶提示的刪除
  • rm -f fall :強制刪除
  • rm -ri my_diir:刪除目錄中的文件,再刪除目錄自己
  • rm -ri my_diir:遞歸刪除目錄中的文件,再刪除目錄自己
3.7 建立目錄
  • mkdir -p New_dir/Sub_dir/under_ir :同時建立多個目錄及子目錄用 -p參數
  • tree New_dir :以樹的形式查看目錄結構
3.8 查看文件內容
  • file my_file :查看文件或者目錄類型
  • cat -n test1 :顯示文本文件數據,並加上行號
  • cat -b test1 :只給有文本的加上行號
  • cat -T test1 :不讓製表符出現
  • more test1 :顯示文件內容,不過會在每一頁後停下來
  • less test1 :跟more差很少,可是更高級,支持方向鍵上下翻頁
  • tail -n 2 test1 :只顯示最後兩行的內容
  • head -n 2 test1 :顯示文件開頭兩行內容

4. 更多的bash shell命令

1.監測程序
  • ps :顯示運行在當前控制檯下的屬於當前用戶的進程
  • ps -ef :顯示全部進程的完整信息
    其餘參數
  • -A 顯示全部進程
  • -N 顯示與指定參數不符的全部進程
  • -a 顯示除控制進程(session leader ① )和無終端進程外的全部進程
  • -d 顯示除控制進程外的全部進程
  • -e 顯示全部進程
  • -C cmdlist 顯示包含在 cmdlist 列表中的進程
  • -G grplist 顯示組ID在 grplist 列表中的進程
  • -U userlist 顯示屬主的用戶ID在 userlist 列表中的進程
  • -g grplist 顯示會話或組ID在 grplist 列表中的進程 ②
  • -p pidlist 顯示PID在 pidlist 列表中的進程
  • -s sesslist 顯示會話ID在 sesslist 列表中的進程
  • -t ttylist 顯示終端ID在 ttylist 列表中的進程
  • -u userlist 顯示有效用戶ID在 userlist 列表中的進程
  • -O format 顯示默認的輸出列以及 format 列表指定的特定列
  • -o format 僅顯示由 format 指定的列
  • -n namelist 定義了 WCHAN 列顯示的值
  • -F 顯示更多額外輸出(相對 -f 參數而言)
  • -M 顯示進程的安全信息
  • -c 顯示進程的額外調度器信息
  • -f 顯示完整格式的輸出
  • -j 顯示任務信息
  • -l 顯示長列表
    F:內核分配給進程的系統標記
    S:進程狀態(O表示正在運行,S表示正在休眠,R表示可運行,正在等待運行,Z表示殭屍進程)
  • -y 不要顯示進程標記(process flag,代表進程狀態的標記)
  • -Z 顯示安全標籤(security context) ① 信息
  • -H 用層級格式來顯示進程(樹狀,用來顯示父進程)
  • -w 採用寬輸出模式,不限寬度顯示
  • -L 顯示進程中的線程
  • -V 顯示 ps 命令的版本號
top :跟ps類似,不過它顯示的是實時的
2.結束進程
  • kill 3904 :給進程ID是3904的進程發送TERM(儘量終止)信號
  • kill -s HUP 3940 :給進程ID是3904的進程發送HUP(掛起)信號
  • killall http* :結束以http開頭的進程
3.檢測磁盤空間
  • mount :列出當前系統上掛載的設備列表
  • mount -t vfat /dev/sdb1 /media/disk :手動將U盤/dev/sdb1掛載到/media/disk目錄下
  • umount /home/rich/mnt :卸載設備
  • df -h :查看全部已掛載設備的的磁盤使用狀況,-h用易讀的方式顯示
  • du /mnt/hgfs :查看特定目錄下的磁盤使用狀況,不加參數表示當前目錄
4.處理數據文件
  • sort -n file :排序file文件,並把數字識別成數字
  • sort -M file3 :按月份(3個字母)排序,經常使用於日誌文件
  • sort -t ‘:’ -k 3 -n /etc/passwd :對密碼文件根據用戶ID排序,-t指定區分鍵位置字符,-k排序其實位置
  • grep three file :在file中搜索three文本
  • grep -v three filre :在file文件中反向搜索three文本,即不包含three的行
  • grep -C three filre :在file文件中反向搜索three文本,只輸出有多少個行含有匹配模式
  • grep -n three filre :在file文件中反向搜索three文本,僅輸出行號
  • grep -e t -e f file :若是要指定多個模式,-e指定每一個模式
  • grep [tf] file :使用正則表達式搜索包含字符t或者f的匹配
  • gzip my* :經過通配符一次性批量壓縮文件
  • gzcat myprog.c.gz :查看壓縮過的文本文件的內容
  • gunzip myprog.c.gz :解壓文件
  • tar -cvf test.tar test/ test2/ :歸檔文件
  • tar -tf test.tar :列出test.tar的內容
  • tar -zxvf file.tgz :解壓用gzip壓縮過的文件

5.理解shell

shell不僅僅是一種CLI,它是一個時刻都在運行的交互式程序linux

/bin/sh:用於那些在系統啓動時使用的系統shell腳本
ps –forest:展現進程間的嵌套結構git

5.1 可經過命令行參數修改shell的啓動方式
  • -c string 從 string 中讀取命令並進行處理
  • -i 啓動一個可以接收用戶輸入的交互shell
  • -l 以登陸shell的形式啓動
  • -r 啓動一個受限shell,用戶會被限制在默認目錄中
  • -s 從標準輸入中讀取命令
5.2 經常使用命令
  • echo $BASH_SUBSHELL :查看子shell的個數
  • sleep 10 :會話暫停10秒鐘
  • sleep 10& :sleep命令睡眠10秒鐘放到後臺運行
  • jobs :顯示當前運行在後臺模式的全部用戶進程(做業)
  • coproc sleep 10 :在後天生成一個子shell,並把命令放到後臺運行
  • coproc My_job { sleep 10; } :給協程命名
5.3 理解shell的內建命令
5.3.1 外部命令:也叫文件系統命令,一般位於/bin、/usr/bin、/sbin或者/usr/sbin中
  • which ps :用which命令找到外部ps命令
  • type ps :跟上面同樣
5.3.2內部命令:不須要使用子進程來執行,做爲shell的組成部分存在
  • type cd :查看cd是否是內部命令
  • history :跟蹤使用過的命令,保存在隱藏文件.bash_history中,位於用戶主目錄
    !! :喚回並重用歷史命令中最近的命令
    history -a :強制將歷史記錄寫入.bash_history
    !20 :喚回歷史命令中的第20條命令
  • alias :查看可用的別名
  • alias ll=’ls -alF’ :設置別名,不過僅在被定義的shell中才有效

6.使用Linux環境變量

bash shell用一個叫作環境變量的(enviroment variable)的特性來存儲有關 shell會話工做環境 的信息
6.1 全局/局部 環境變量
—-全局環境變量對於shell會話和全部生成的字shell都是可見的
—-局部變量則只對建立他們的shell可見
+ printenv :查看全部全局變量
+ printenv HOME :查看單個環境變量
+ env HOME :查看單個全局變量
+ echo H O M E : + l s HOME :經過"$」引用HOME的值
+ set :顯示全部全局、局部和用戶自定義的環境變量github

6.2設置用戶定義變量
+ my_variable=hello :變量名、等號和值之間沒有空格,在子shell中不能用,退出shell後也會被清除
+ echo v a r i a b l e : + e x p o r t m y v a r i a b l e : s h e l l s h e l l 使 e x p o r t + u n s e t m y v a r i a b l e : + m y p r o g : + e x p o r t P A T H = PATH:. #修改環境變量,持續到退出或重啓系統正則表達式

6.3 定位系統環境變量
當登入Linux系統啓動一個bash shell時,默認狀況下bash會在幾個文件中查找命令,這些文件叫 啓動文件環境文件shell

6.3.1 登陸shell
  • 登陸linux系統時,bash shell會做爲默認shell啓動,登陸shell會從5個不一樣的啓動文件裏讀取命令
     /etc/profile :主啓動文件,每一個用戶登陸都會執行
    H O M E / . b a s h p r o f i l e HOME/.bashrc:’.’開頭的通常是隱藏文件,這個文件一般經過其餘文件運行
    H O M E / . b a s h l o g i n HOME/.profile
6.3.2 交互式shell進程(CLI中敲bash)
  • 只檢查HOME目錄下的.bashrc文件
    • 查看、/etc目錄下通用的bashrc文件
    • 爲用戶提供一個定製本身的命令別名和私有腳本函數的地方

6.3.3 非交互式shell (執行shell腳本時使用)
__6.4 環境變量的持久化__ + 放入/etc/profile:升級後就沒有了 + 在/etc/profile.d目錄中建立一個.sh腳本:這是最好的方法 + 放入 HOME/.bashrc:存儲我的永久變量的最好方法__6.5 數組變量__mytest=(one two three four five)  :值放括號,值之間用空格隔開echo {mytest[2]} :引用單獨的數組元素,索引值要用方括號 echo ${mytest[*]} :顯示整個數組元素 mytest[2]=severn :能夠改變索引位置的值 unset mytest[2] :刪除至關於mytest[2]=」」

7.理解Linux文件權限

linux安全系統的核心是用戶帳戶。用戶權限是經過建立用戶時分配的用戶ID(縮寫爲UID) __7.1 /etc/passwd文件__ + __系統帳戶__:系統上運行的各類服務進程訪問資源用的特殊帳戶,全部運行在後臺的服務都須要用一個系統用戶帳戶登陸到Linux系統上 + 用戶密碼被設置成了x,這是由於保存到了 __/etc/shadow__ 文件 + __/usr/sbin/useradd hzq -m -p h__ :建立一個用戶hzq,密碼是h,若是不加選項,會按照/etc/default/useradd文件默認配置,能夠-D選項查看,加上-m後會建立home目錄並將 **/etc/skel** 目錄中的文件複製過來 + **userdel -r hzq** :刪除帳戶,同時刪除/home目錄下的hzq文件夾 + **usermod hzq -p 123** :修改用戶密碼 + **passwd hzq** :修改用戶密碼或用來修改當前用戶密碼 + chpasswd
7.2.1 /etc/group 文件
  • 共有四個字段:組名、組密碼、GID、屬於該組的用戶列表(空表示在/etc/passwd中指定了默認組)
  • 系統帳戶的GID低於500,用戶的組ID從500/1000之後開始分配
  • /usr/sbin/groupadd shared :建立組
  • usermod -G shared hzq :將用戶添加到組,從新登陸後關係生效
  • groupmod -n sharing shared :修改組名與GID

7.3 理解文件權限express

ls -l 輸出的第一個字符表明了對象的類型

 - 表明文件
 d 表明目錄
 l 表明連接
 c 表明字符型設備
 b 表明塊設備
 n 表明網絡設備編程

ls -l 第一個字段以後有3組三字符的編碼。每一組定義了3種訪問權限(若沒有某種權限,在該權限位會出現單破折線):

 r 表明對象是可讀的
 w 表明對象是可寫的
 x 表明對象是可執行的vim

這3組權限分別對應對象的3個安全級別

 對象的屬主
 對象的屬組
 系統其餘用戶
用戶權限.png
+ umask 026 :用 umask 命令爲默認 umask 設置指定一個新值,一樣會做用在建立目錄上,見/etc/login.defs或/etc/profile

7.4 改變安全性設置
+ chmod 760 newfile :八進制模式設置
+ chmod o+r newfile :符號模式,[ugoa…][[+-=][rwxXstugo…]

 u 表明用戶
 g 表明組
 o 表明其餘
 a 表明上述全部
 X :若是對象是目錄或者它已有執行權限,賦予執行權限。
 s :運行時從新設置UID或GID。
 t :保留文件或目錄。
 u :將權限設置爲跟屬主同樣。
 g :將權限設置爲跟屬組同樣。
 o :將權限設置爲跟其餘用戶同樣。
+ chown hzq.shared newdir -R:可用登陸名或UID來指定文件的新屬主.屬組,遞歸地改變子目錄和文件的所
屬關係
+ chown hzq. newfile :若是你的Linux系統採用和用戶登陸名匹配的組名,能夠只用一個條目就改變兩者。
+ chgrp shared newfile :更改文件或目錄的默認屬組

7.5 共享文件
+ chmod g+s testdir :使目錄裏的新文件都能沿用目錄的屬組,只需將該目錄的SGID位置位,等效於:chmod 2776 testdir
+ Linux還爲每一個文件和目錄存儲了3個額外的信息位。
 粘着位:進程結束後文件還駐留(粘着)在內存中。
 設置組ID(SGID):對文件來講,程序會以文件屬組的權限運行;對目錄來講,目錄中建立的新文件會以目錄的默認屬組做爲默認屬組。
 設置用戶ID(SUID):當文件被用戶使用時,程序會以文件屬主的權限運行。

8. 管理文件系統

8.1 日誌文件系統

    1. ext4文件系統 : 在2008年受到Linux內核官方支持
      區段(extent)的特性:區段在存儲設備上按塊分配空間,但在索引節點表中只保存起始塊的位置
      塊預分配技術(block preallocation):ext4文件系統用 0 填滿預留的數據塊,不會將它們分配給其餘文件
    1. Reiser文件系統:只支持回寫日誌模式——只把索引節點表數據寫到日誌文件—->最快的日誌文件系統之一
      能夠在線調整已有文件系統的大小—->最快的日誌文件系統之一
      尾部壓縮(tailpacking),該技術能將一個文件的數據填進另外一個文件的數據塊中的空白空間

8.2 寫時複製文件系統(COW)

    1. ZFS文件系統
    1. Btrf文件系統

8.3 操做文件系統

。。。。。。。。。。

9. 安裝軟件程序

  • yum list installed : 找出系統上已安裝的包
  • yum list updates :列出須要更新的
  • 從源碼安裝:
    1. tar -zxvf sysstat-11.1.1.tar.gz :解壓
    2. cd sysstat-11.1.1 :進入解壓目錄
    3. ./configure :檢查,確保它擁有合適的編譯器可以編譯源代碼,另外還要具有正確的庫依賴關係
    4. make :構建各類二進制文件
    5. make install :安裝到Linux系統中經常使用的位置上

10. 使用編輯器

10.1 vim 編輯器

  • 10.1.1 普通模式
     h :左移一個字符。
     j :下移一行(文本中的下一行)。
     k :上移一行(文本中的上一行)。
     l :右移一個字符。
     PageDown (或Ctrl+F):下翻一屏。
     PageUp (或Ctrl+B):上翻一屏。
     G :移到緩衝區的最後一行。
     num G :移動到緩衝區中的第 num 行。
     gg :移到緩衝區的第一行。
     w filename :將文件保存到另外一個文件中
    刪除:x(取叉、錯的意思):刪除當前光標所在位置的字符
    刪除:dd(delete ):刪除當前光標所在行,至關於剪切
    刪除:dw(delete word):刪除當前光標所在位置的單詞
    刪除:d ( d e l e t e ) 刪除當前光標所在位置至行尾的內容
    拼接行:J(join ),刪除當前光標所在行行尾的換行符
    撤銷:u(unsure)
    追加數據 :a(add),相似於 「i」
    行尾追加 : A(Add)
    insert:r char(char表示一個字符):用 char 替換當前光標所在位置的單個字符
    insert:R text(至關於insert)直到按下ESC鍵
    複製:v—->移動光標—->y—->p
    查找:/+string—–>n(next)
    替換:s/old/new/
     :s/old/new/g :一行命令替換全部 old 。
     :n,ms/old/new/g :替換行號 n 和 m 之間全部 old 。
     :%s/old/new/g :替換整個文件中的全部 old 。
     :%s/old/new/gc :替換整個文件中的全部 old ,但在每次出現時提示。

10.2 nano 編輯器

10.3 emacs 編輯器

10.4 KWrite 編輯器

10.5 Kate(kdesdk) 編輯器

10.6 gedit編輯器

11. shell 腳本編程基礎

11.1 顯示消息

#!/bin/bash
# This script displays the date and who's logged on
echo -n The time and date are:                 #注意-n選項不換行
date
echo "Let's see who's logged into the system:" #全部的引號均可以正常輸出了
who                                            #能夠將 echo 語句添加到shell腳本中任何須要顯示額外信息的地方

11.2 使用變量

#!/bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID                      #1.環境變量名稱以前加上美圓符"$"來使用這些環境變量
echo HOME: "$HOME"                  #2.加上雙引號也沒有問題
echo "The cost of the item is \$15" #3.想顯示"$"符號須要在前面加上反斜槓
# testing variables
days=10                             #4.shell腳本會自動決定變量值的數據類型
guest="Katie"                       #5.變量名區分大小寫
echo "$guest checked in $days days ago"
days=5                              #6.賦值時不用$,可是引用必須用$符號
guest="Jessica"
echo "$guest checked in $days days ago"
                                    #7.在shell腳本結束時變量會被刪除掉
#有兩種方法能夠將命令輸出賦給變量:
#1. 反引號字符( ` )  :注意不是單引號(')
#2. $() 格式                                   
one=`date`                          #8.shell命令的輸出賦給變量方法1
two=$(date)                         #9.賦值等號和命令替換字符之間沒有空格
echo "The date and time are: " $one #
#下面這個例子很常見,它在腳本中經過命令替換得到當前日期並用它來生成惟一文件名。
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d)               #today存儲日期
ls /usr/bin -al > log.$today        #ls的輸出重定向到log.180515文件中,若是輸出文件已經存在了,重定向操做符會用新的文件數據覆蓋已有文件(默認的 umask 設置)

11.3 重定向輸入和輸出

  • 輸入重定向符號是小於號( < )
    wc < test6 :wc 命令能夠對對數據中的文本進行計數(行數、詞數、字節數)
  • 內聯輸入重定向符號是遠小於號(<<)
  • 管道:將一個命令的輸出做爲另外一個命令的輸入。這能夠用重定向來實現
    rpm -qa | sort | more :排序rmp輸出的軟件包列表

11.4 執行數學運算

在shell腳本中有兩種途徑來進行數學運算
+ expr 1 + 5 :計算加法表達式
+ expr 5 * 2 :計算乘法表達式

ARG1 | ARG2
若是 ARG1 既不是null也不是零值,返回 ARG1 ;不然返回 ARG2
ARG1 & ARG2
若是沒有參數是null或零值,返回 ARG1 ;不然返回 0
ARG1 < ARG2
若是 ARG1 小於 ARG2 ,返回 1 ;不然返回 0
ARG1 <= ARG2
若是 ARG1 小於或等於 ARG2 ,返回 1 ;不然返回 0
ARG1 = ARG2
若是 ARG1 等於 ARG2 ,返回 1 ;不然返回 0
ARG1 != ARG2
若是 ARG1 不等於 ARG2 ,返回 1 ;不然返回 0
ARG1 >= ARG2
若是 ARG1 大於或等於 ARG2 ,返回 1 ;不然返回 0
ARG1 > ARG2
若是 ARG1 大於 ARG2 ,返回 1 ;不然返回 0
ARG1 + ARG2
返回 ARG1 和 ARG2 的算術運算和
ARG1 - ARG2
返回 ARG1 和 ARG2 的算術運算差
ARG1 * ARG2
返回 ARG1 和 ARG2 的算術乘積
ARG1 / ARG2
返回 ARG1 被 ARG2 除的算術商
ARG1 % ARG2
返回 ARG1 被 ARG2 除的算術餘數
STRING : REGEXP
若是 REGEXP 匹配到了 STRING 中的某個模式,返回該模式匹配
match STRING REGEXP
若是 REGEXP 匹配到了 STRING 中的某個模式,返回該模式匹配
substr STRING POS LENGTH
返回起始位置爲 POS (從 1 開始計數)、長度爲 LENGTH 個字符的子字符串
index STRING CHARS
返回在 STRING 中找到 CHARS 字符串的位置;不然,返回 0
length STRING
返回字符串 STRING 的數值長度
_ + TOKEN :將 TOKEN 解釋成字符串,即便是個關鍵字
(EXPRESSION) : 返回 EXPRESSION 的值

  • var1=$[1 + 5] : 用美圓符和方括號將數學表達式圍起來
  • variable=$(echo 「options; expression」 | bc) :浮點解決方案之在腳本中使用 bc
#!/bin/bash
var1=100
var2=45
var3=$(echo "scale=4; $var1 / $var2" | bc)#將 scale 變量設置成了四位小數,並在 expression 部分指定了特定的運算
echo The answer for this is $var3
  • 浮點解決方案之最好的解決方案:使用內聯輸入重定向, 注意下面的註釋:不能加Tab
#!/bin/bash
var1=10.23
var2=43.12
var3=33.2
var4=31
var5=$(bc<<EOF
scale = 4            #注意不能加tab鍵
a1 = ($var1 * $var2)
b1 = ($var3 * $var4)
a1 + b1
EOF
)
echo The final answer for this mess is $var5

11.5 退出腳本

  • 對於須要進行檢查的命令,必須在其運行完畢後馬上查看或使用 $? 變量。它的值會變成由shell所執行的最後一條命令的退出狀態碼
  • Linux退出狀態碼

    0命令成功結束
    1 通常性未知錯誤
    2 不適合的shell命令
    126 命令不可執行
    127 沒找到命令
    128 無效的退出參數
    128+x 與Linux信號x相關的嚴重錯誤
    130 經過Ctrl+C終止的命令
    255 正常範圍以外的退出狀態碼

  • exit 命令:容許你在腳本結束時指定一個退出狀態碼
    如:exit 5

#!/bin/bash
#shell中運行的每一個命令都使用退出狀態碼(exit status)告訴shell它已經運行完畢
var1=10
var2=30
var3=$[$var1 + $var2]
exit $var3            #exit 命令的參數中使用變量
                      #若是值大於255,返回模256後獲得的餘數

12. 使用結構化命令

12.1 使用if-then-fi語句

  • bash shell的 if 語句會運行 if 後面的那個命令。若是該命令的退出狀態碼(參見第11章)是 0(該命令成功運行),位於 then 部分的命令 纔會 被執行
#!/bin/bash
# 這個腳本在 if 行採用了 pwd 命令。若是命令成功結束, echo 語句就會顯示該文本字符串
if pwd
then
    echo "It worked"
fi
if IamNotaCommand       #因爲這是個錯誤的命令,因此它會產生一個非零的退出狀態碼
then
    echo "It "
    echo "worked"       #這裏能夠放多條明令
else
    echo "It not worked!"
fi

12.2 if-then嵌套

#!/bin/bash
# 甚至能夠更進一步,讓腳本檢查擁有目錄的不存在用戶以及沒有擁有目錄的不存在用戶。這
# 能夠經過在嵌套 elif 中加入一個 else 語句來實現。
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
then
    echo "The user $testuser exists on this system."
#
elif ls -d /home/$testuser      #每塊命令都會根據命令是否會返回退出狀態碼 0 來執行。記住,bash shell會依次執行 if 語句,
                                #只有第一個返回退出狀態碼 0 的語句中的 then 部分會被執行
then
    echo "The user $testuser does not exist on this system."
    echo "However, $testuser has a directory."
#
else
    echo "The user $testuser does not exist on this system."
    echo "And, $testuser does not have a directory."
fi

12.3 test 命令

  • 幫助經過 if-then 語句測試其餘條件
  • 12.2.1 數值比較
    n1 -eq n2
    檢查 n1 是否與 n2 相等
    n1 -ge n2
    檢查 n1 是否大於或等於 n2
    n1 -gt n2
    檢查 n1 是否大於 n2
    n1 -le n2
    檢查 n1 是否小於或等於 n2
    n1 -lt n2
    檢查 n1 是否小於 n2
    n1 -ne n2
    檢查 n1 是否不等於 n2
#!/bin/bash
# Using numeric test evaluations
#使用中括號進行數值測試
value1=10
value2=11
#
if [ $value1 -gt 5 ]  #可是隻能測試整數
then
    echo "The test value $value1 is greater than 5"
fi
#
if [ $value1 -eq $value2 ]
then
    echo "The values are equal"
else
    echo "The values are different"
fi
  • 12.3.2 字符串比較

    str1 = str2
    檢查 str1 是否和 str2 相同
    str1 != str2
    檢查 str1 是否和 str2 不一樣
    str1 < str2
    檢查 str1 是否比 str2 小
    str1 > str2
    檢查 str1 是否比 str2 大
    -n str1
    檢查 str1 的長度是否非0
    -z str1
    檢查 str1 的長度是否爲0

  • 在比較測試中,大寫字母被認爲是小於小寫字母的。但 sort 命令剛好相反,由於sort使用的是系統的本地化語言設置中定義的排序順序,而比較測試中使用的是標準的ASCII順序

  • -n(not zero) 和 -z (zoro)能夠檢查一個變量是否含有數據
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ]     #注意,必須加斜槓,不然會被當成重定向符
then
    echo "$val1 is greater than $val2"
else
    echo "$val1 is less than $val2"
fi

# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
echo "The string '$val1' is not empty"
else
echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ]
then
echo "The string '$val2' is empty"
else
echo "The string '$val2' is not empty"
fi
#
if [ -z $val3 ]
then
echo "The string '$val3' is empty"
else
echo "The string '$val3' is not empty"
fi

12.3.3 文件比較

檢查 file 是否存在並是一個目錄 -d file
檢查 file 是否存在 -e file
檢查 file 是否存在並是一個文件 -f file
檢查 file 是否存在並可讀 -r file
檢查 file 是否存在並不是空 -s file
檢查 file 是否存在並可寫 -w file
檢查 file 是否存在並可執行 -x file
檢查 file 是否存在並屬當前用戶全部 -O file
檢查 file 是否存在而且默認組與當前用戶相同 -G file
檢查 file1 是否比 file2 新 ,必須先確認文件是存在的 file1 -nt file2
檢查 file1 是否比 file2 舊 file1 -ot file2
#!/bin/bash
# Look before you leap
# 文件測試
jump_directory=/home/hzq
#
if [ -d $jump_directory ]
then
    echo "The $jump_directory directory exists"
cd $jump_directory
ls
else
    echo "The $jump_directory directory does not exist"
fi

12.4 複合條件測試

if-then 語句容許你使用布爾邏輯來組合測試。有兩種布爾運算符可用:
+ [ condition1 ] && [ condition2 ]
+ [ condition1 ] || [ condition2 ]

12.5 if-then 的高級特性

  • 用於數學表達式的雙括號
#!/bin/bash
# using double parenthesis
#
val1=10
#
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
# val++ 後增
# val-- 後減
# ++val 先增
# --val 先減
# ! 邏輯求反
# ~ 位求反
# ** 冪運算
# << 左位移
# >> 右位移
# & 位布爾和
# | 位布爾或
# && 邏輯和
# || 邏輯或
  • 用於高級字符串處理功能的雙方括號:除了test提供的標準字符串比較,還提供的另外一個特性——模式匹配
#!/bin/bash
# using pattern matching
# 使用模式匹配
if [[ $USER == r* ]]
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
fi

12.6 case命令

#!/bin/bash
# using the case command
# 使用case命令
case $USER in
rich | barbara)
    echo "Welcome, $USER"
    echo "Please enjoy your visit";;
testing)
    echo "Special testing account";;
jessica)  #")"至關於C語言中的":"
    echo "Do not forget to log off when you're done";;
*)        #*通配符即匹配全部狀況
echo "Sorry, you are not allowed here";;
esac      #case語句結束

13. 更多的結構化命令

13.1 for命令

#!/bin/bash
# another example of how not to use the for command
for test in I don\'t know if "this'll" work #不添加反斜槓會被視做一個字符串 do #若是一個詞語中有空格,須要用雙引號圈起來 echo "word:$test" done

13.1.1 list能夠從命令中讀取

#!/bin/bash
# reading values from a file
file="states"
for state in $(cat $file)
do
echo "Visit beautiful $state"
done

13.1.2 更改字段分隔符

for語句中的list中,環境變量 IFS(內部字段分隔符)默認會用空格、製表符、換行符做爲分隔符
+ IFS.OLD= I F S I F S = ’\n’:;」 :使用換行、冒號、分號做爲分隔符
<在代碼中使用新的IFS值>
IFS=$IFS.OLD :修改使只識別換行符

13.2 C 語言風格的 for 命令

#!/bin/bash
# testing the C-style for loop
for (( i=1; i <= 10; i++ ))  #1.變量賦值能夠有空格
do                           #2.條件中的變量不以美圓符開頭
echo "The next number is $i" #3.迭代過程的算式未用 expr 命令格式
done
##############################
# multiple variables
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
##############################

13.3 while命令

#!/bin/bash
# testing a multicommand while loop
var1=10
while echo $var1  #檢查 var1 是否大於等於 0
[ $var1 -ge 0 ]   #只有最後一個測試命令的退出狀態碼會被用來決定何時結束循環
do                #每次迭代中全部的測試命令都會被執行,區別於C語言的 || 
echo "This is inside the loop"
var1=$[ $var1 - 1 ]
done

13.4 until 命令

#!/bin/bash
# using the until command
var1=100
until echo $var1  #shell會執行指定的多個測試命令,只有在最後一個命令成立時中止
[ $var1 -eq 0 ]   #退出狀態碼不爲0,才執行循環中列出的命令
do                # -eq :檢查是否相等
    echo Inside the loop: $var1
    var1=$[ $var1 - 25 ]
done

13.5 嵌套循環

$ cat test14
#!/bin/bash
# nesting for loops
for (( a = 1; a <= 3; a++ ))
do
    echo "Starting loop $a:"
    for (( b = 1; b <= 3; b++ ))
    do
        echo " Inside loop: $b"
    done
done

13.6 循環處理文件數據

#!/bin/bash
# changing the IFS value
# 經過改變IFS的值處理 /etc/passwd文件
IFS.OLD=$IFS
IFS=$'\n'      #先按行處理文件數據
for entry in $(cat /etc/passwd)
do
    echo "Values in $entry –"
    IFS=:      #再把每一行用空格分開
    for value in $entry
    do
        echo " $value"
    done
done

13.7 控制循環

  • break 命令
#!/bin/bash
# breaking out of an outer loop
for (( a = 1; a < 4; a++ ))
do
    echo "Outer loop: $a"
    for (( b = 1; b < 100; b++ ))
    do
        if [ $b -gt 4 ]
        then
            break 2      #1.注意,加上參數這裏能夠跳出兩層循環
        fi
        echo " Inner loop: $b"
    done
done
  • continue 命令
#!/bin/bash
# continuing an outer loop
for (( a = 1; a <= 5; a++ ))
do
    echo "Iteration $a:"
    for (( b = 1; b < 3; b++ ))
    do
        if [ $a -gt 2 ] && [ $a -lt 4 ]
        then
            continue 2   #1.加上參數指定要繼續執行哪一級循環
        fi
        var3=$[ $a * $b ]
        echo " The result of $a * $b is $var3"
    done
done

13.8 處理循環的輸出

#!/bin/bash
for file in /home/hzq/*
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif [ -f "$file" ]
    then
        echo "$file is a file"
    fi
done

13.9 實例

  • 13.9.1 查找可執行文件(經過PATH)
#!/bin/bash
# finding files in the PATH

IFS=:
for folder in $PATH  #1.遍歷每個PATH目錄中的路徑
do
    echo "$folder:"  #2. 打印這些路徑
    echo "$IFS"      
    for file in $folder/* #爲何IFS是":",可是這裏仍是能分開
    do
        echo "$IFS" 
        if [ -x $file ]
        then
            echo " $file"
        fi
    done
done

14. 處理用戶輸入

14.1 命令行參數的讀取

#!/bin/bash
# using one command line parameter
#
factorial=1
for (( number = 1; number <= $1 ; number++ ))
do
    factorial=$[ $factorial * $number ]
done
echo The factorial of $1 is $factorial
if [ -n "$1" ]&&[ -n "$2" ]            #0.注意:這裏必須加引號
then
    total=$[ $1 * $2 ]                 #1.一個參數乘以第二個參數
    echo The first parameter is $1.    #2.參數也能夠是字符串,以空格分隔
    echo The second parameter is $2.   #3.若是參數不止9個,能夠用花括號:${10}
    echo The total value is $total.
else
    echo "please input two number"
fi
echo "$0 is run in the end"             #4.$0保存的是腳本的名字
#潛在問題:若是使用另外一個命令來運行shell腳本,命令會和腳本名混在一塊兒,出如今 $0 參數中。
echo "$(basename $0)is run in the end " #不過能夠這樣解決

14.2 特殊參數變量

#!/bin/bash
# testing $* and $@
#
echo
count=1
#
for param in "$*"   #$* :全部的參數
do
    echo "\$* Parameter #$count = $param"
    count=$[ $count + 1 ]
done
#
echo
count=1
#
for param in "$@"
do               #$@ :將參數視做單獨的單詞
    echo "\$@ Parameter #$count = $param"
    count=$[ $count + 1 ]
done

14.3 移動參數

#!/bin/bash
# demonstrating the shift command
echo
count=1
while [ -n "$1" ]
do
echo "Parameter #$count = $1"
count=$[ $count + 1 ]
shift  2                   #向左移動參數,可是$0不變,加上參數表示一次移動兩個
done

14.4 處理選項

  • 使用getopt命令
    set -- $(getopt -q ab:cd "$@")
#!/bin/bash
# Extract command line options & values with getopt
#
set -- $(getopt -q ab:cd "$@")
#
echo
while [ -n "$1" ]
do
    case "$1" in
        -a) echo "Found the -a option" ;;
        -b) param="$2"
            echo "Found the -b option, with parameter value $param"
            shift ;;
        -c) echo "Found the -c option" ;;
        --) shift
            break ;;
        *) echo "$1 is not an option";;
    esac
    shift
done
#
count=1
for param in "$@"
do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done
#須要注意的是:getopt 命令並不擅長處理帶空格和引號的參數值,以下面這種狀況 
#$ ./32_getopt.sh -a -b test1 -cd "test2 test3" test4
  • 更加高級的getopts
#!/bin/bash
# Processing options & parameters with getopts
#
echo
while getopts :ab:cd opt              #指明要查找哪些命令行選項,以及每次迭代中存儲它們的變量名(opt)
do
case "$opt" in
    a) echo "Found the -a option" ;;  #注意這裏沒有單破折號,已經移除了
    b) echo "Found the -b option, with value $OPTARG" ;;
    c) echo "Found the -c option" ;;
    d) echo "Found the -d option" ;;
    *) echo "Unknown option: $opt" ;;
esac
done
#
shift $[ $OPTIND - 1 ]
#
echo
count=1
for param in "$@"
do
    echo "Parameter $count: $param"
    count=$[ $count + 1 ]
done
#./32_getopt.sh -b "test1 test2" -a :如今能夠正常解析空格了
#./32_getopt.sh -abtest1 :將選項字母和參數值放在一塊兒使用,而不用加空格
#./32_getopt.sh -acde :將命令行上找到的全部未定義的選項統一輸出成問號

14.5 將選項標準化

14.6 得到用戶的輸入

#!/bin/bash
# testing the read -p option
#
#
echo -n "Enter your name: "             # -n 參數使不換行
read name
echo "Hello $name, welcome to my program. "
                                        # -t 指定等待的秒數 
read  -t 5 -p "Enter your name: "       # 不指定變量,數據會放入特殊環境變量REPLY中
echo Hello $REPLY, welcome to my program.

read -p "Please enter your age: " age   # -p 命令直接指定提示字符串
days=$[ $age * 365 ]
echo "That makes you over $days days old! "

read -n1 -p "Do you want to continue [Y/N]? " answer
case $answer in                         # -n 參數指定接收的輸入個數
Y | y) echo
echo "fine, continue on…";;
N | n) echo
echo OK, goodbye
exit;;
esac
                                        # -s 參數避免在命令中輸入的數據出如今顯示器上
read -s -p "Enter your password: " pass #事實是會顯示,只是跟背景色同樣
echo "Is your password really $pass? "

14.6.1 從文件中讀取

#!/bin/bash
# reading data from a file

count=1
test="34_read_input.sh"
cat $test | while read line    #1.每次讀取一行
do                             #2.
    echo "Line $count: $line"
    count=$[ $count + 1]
done
echo "Finished processing the file"

15. 呈現數據

15.1 理解輸入和輸出

  • ls -l > test2 :重定向輸出
  • cat < test2 :重定向輸入
  • who >> test2 :將數據追加到文件
  • ls -al badfile > test3 :注意這句,錯誤不會輸出到顯示器,可是會建立test3文件
  • ls -al badfile 2> test4 :只重定向錯誤消息, 由於系統設置STDERR 描述符是2
  • ls -al test test2 test3 badtest 2> test6 1> test7 :重定向錯輸出和錯誤
  • ls -al test test2 test3 badtest &> test7 :將 STDERR 和 STDOUT 的輸出重定向到同一個輸出文件,注意 shell自動賦予了錯誤消息更高的優先級

15.2 在腳本中重定向輸出

  • 臨時重定向
    echo "This is an error" >&2 :有意生成一條錯誤信息
  • 永久重定向
    exec 1>testout :用 exec 命令告訴shell在腳本執行期間重定向某個特定文件描述符
  • 在腳本中重定向輸入
    exec 0< testfile : exec 命令容許你將 STDIN 重定向到Linux系統上的文件中

14.3 建立本身的重定向

  • 建立輸出文件描述符
#!/bin/bash
# using an alternative file descriptor
exec 3>test13out                 #能夠用 exec 命令來給輸出分配文件描述符
#exec 3>>test13out #也可使用 exec 命令來將輸出追加到現有文件中
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor"
  • 重定向文件描述符
#!/bin/bash
# storing STDOUT, then coming back to it
exec 3>&1                                   #1.文件描述符3重定向到標準輸出
exec 1>test14out                            #2.標準輸出重定向到文件
echo "This should store in the output file"
echo "along with this line."
exec 1>&3                                   #3.利用該文件描述符3重定向回 STDOUT
echo "Now things should be back to normal"  #+.這句輸出到屏幕
  • 建立輸入文件描述符
#!/bin/bash
# redirecting input file descriptors
exec 6<&0          #1.先用文件描述符 6 用來保存 STDIN 的位置
exec 0< testfile   #2.將 STDIN 重定向到一個文件
count=1
while read line    #3.read命令的全部輸入都來自重定向後的 STDIN
do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
exec 0<&6          #4.將 STDIN 恢復到原先的位置
read -p "Are you done now? " answer
case $answer in
Y|y) echo "Goodbye";;
N|n) echo "Sorry, this is the end.";;
esac
  • 建立讀寫文件描述符
#!/bin/bash
# testing input/output file descriptor
exec 3<> testfile       #1.用exec命令將文件描述符 3 分配給文件 testfile 以進行文件讀寫
read line <&3           #2.用 read 命令讀取文件中的第一行
echo "Read: $line"      #3.須要注意:寫入文件中的數據會覆蓋已有的數據
echo "This is a test line" >&3
  • 關閉文件描述符
#!/bin/bash
# testing closing file descriptors
exec 3> test17file
echo "This is a test line of data" >&3
exec 3>&-                   #1.要關閉文件描述符,將它重定向到特殊符號 &-
echo "This won't work" >&3  #2.這裏shell會生成錯誤消息
cat test17file              #3.打開了同一個輸出文件,shell會用一個新文件來替換已有文件
exec 3> test17file         
echo "This'll be bad" >&3   #4.因此意味着這幾句話會覆蓋已有文件

15.5 列出打開的文件描述符

  • /usr/sbin/lsof -a -p $$ -d 0,1,2
    • -p選項指定進程
    • -d指定要顯示的文件描述符
    • 特殊環境變量$$表示當前進程的PID
    • -a選項用來對其餘選項的結果進行布爾AND運算
      ### 15.6 阻止命令輸出
    • ls -al > /dev/null :shell輸出到null文件的任何數據都不會保存,所有都被丟棄
    • cat /dev/null > testfile :這個文件一般用它來快速清除現有文件中的數據
      ### 15.7 建立臨時文件
    • mktemp testing.XXXXXX
    • mktemp 命令能夠在/tmp目錄中建立一個惟一的臨時文件
    • 不會用默認的 umask 值
    • 參數能夠是文件模板後面跟6個X
#!/bin/bash
#creating and using a temp file
tempfile=$(mktemp test19.XXXXXX)      #生產一個臨時文件
exec 3>$tempfile                      #輸出重定向到該文件
echo "This script writes to temp file $tempfile"
echo "This is the first line" >&3     
echo "This is the second line." >&3
echo "This is the last line." >&3 
exec 3>&-                             #關閉文件描述符
echo "Done creating temp file. The contents are:"
cat $tempfile
rm -i $tempfile 2> /dev/null          #刪除文件,並把刪除的提示信息輸出到/dev/null,即不顯示
  • mktemp -t test.XXXXXX :強制在/tmp目錄下建立文件,返回全路徑
#!/bin/bash
# using a temporary directory
tempdir=$(mktemp -d dir.XXXXXX)   #建立臨時文件夾
cd $tempdir
tempfile1=$(mktemp temp.XXXXXX)   
tempfile2=$(mktemp temp.XXXXXX)
exec 7> $tempfile1                #重定向文件描述符到文件
exec 8> $tempfile2
echo "Sending data to directory $tempdir"
echo "This is a test line of data for $tempfile1" >&7
echo "This is a test line of data for $tempfile2" >&8

15.8 記錄消息

  • date | tee -a testfile
    • date輸出的消息同時輸出的顯示器和文件testfile
    • -a選項表示是以追加的方式寫入

16. 控制腳本

16.1 處理信號

#!/bin/bash
# Modifying a set trap
#
trap "echo ' Sorry... Ctrl-C is trapped.'" SIGINT
              #捕獲"終止進程"信號
count=1
while [ $count -le 5 ]
do
    echo "Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done
#
trap "echo ' I modified the trap!'" SIGINT
               #到這裏處理信號的方式已經變了
count=1
while [ $count -le 5 ]
do
    echo "Second Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done
trap -- SIGINT #刪除設置好的捕獲,單破折號也能起做用
echo "Ctrl-C can use le"
count=1
while [ $count -le 5 ]
    echo "Second Loop #$count"
    sleep 1
    count=$[ $count + 1 ]
done

16.2 之後臺模式運行腳本

  • ./test4.sh & :只須要像這樣,在命令後面加一個&,可是這樣仍是會有輸出,不要奇怪

16.3 在非控制檯下運行腳本

  • nohup ./test1.sh & :能夠用nohup命令,阻斷全部發送給該進程的SIGHUP信號,輸出會被保存到nohup.out文件中

16.4 做業控制

  • jobs -l
    • jobs 命令能夠查看分配給shell的做業
    • -l 參數顯示做業的PID
    • -n 只列出上次shell發出的通知後改變了狀態的做業
    • -p 只列出做業的PID
    • -r 只列出運行中的做業
    • -s 只列出已中止的做業
    • 帶加號的做業會被當作默認做業
    • 當前的默認做業完成處理後,帶減號的做業成爲下一個默認做業
  • bg :之後臺模式重啓一個做業,若是有多個就得加做業號
  • fg 2:之前臺模式重啓做業,可用帶有做業號的 fg 命令

16.5 調整謙讓度

從-20(最高優先級)到+19(最低優先級),默認以0優先級啓動,能夠記作」好人難作」
+ nice -n 10 ./test4.sh > test4.out &:nice命令指定運行的優先級
+ ps -p 4973 -o pid,ppid,ni,cmd,能夠用這個命令驗證
+ -n 選線不是必須的,只須要指定優先級就好了
+ 可是像下降優先級必須得有root權限
+ renice -n 10 -p 5055
+ renice命令容許改變已經運行進程的優先級
+ 只能對屬於你的進程執行 renice
+ 只能經過 renice 下降進程的優先級
+ root用戶能夠經過 renice 來任意調整進程的優先級

16.6 定時運行做業

  • at [-f filename] time:指定Linux系統什麼時候運行腳本
    • 如:at -M -f ./test.sh 10:15
      • 10:15 PM :AM/PM指示符格式
      • now、noon、midnight或者teatime(4 PM) :特定可命名時間
      • MMDDYY、MM/DD/YY或DD.MM.YY:標準日期格式
      • Jul 4或Dec 25:文本日期,加不加年份都可
      • 也能夠指定時間增量,(當前時間+25 min,明天10:15 PM,10:15+7天)
    • 能夠用 -q 參數指定不一樣的隊列字母
    • -f 用來指定腳本文件
    • -M 選項來屏蔽做業產生的輸出信息
  • atq:查看系統中有哪些做業在等待
  • atrm 18:根據做業號刪除指定做業

16.7 cron

  • cron時間表
    • min hour dayofmonth month dayofweek command
    • 15 10 * * * command :天天15.10運行一個命令
    • 15 16 * * 1 command:每週一4:15 PM運行的命令
    • 00 12 1 * * command :每月的第一天中午12點執行命令
    • 00 12 * * * if [ date +%d -d tomorrow = 01 ] ; then ; command :每月的最後一天執行的命令
    • 15 10 * * * /home/rich/test4.sh > test4out :能夠添加任何想要的命令行參數和重定向符號
  • 構建cron時間表
    • crontab -l :列出corn時間表
    • 能夠用 -e 選項來添加條目
  • 瀏覽cron目錄(有4個基本目錄:hourly、daily、monthly和weekly)
    • ls /etc/cron.*ly :查看這四個目錄
    • 若是腳本須要天天運行一次,只要將腳本複製到daily目錄,cron就會天天執行它
  • anacron程序
    • anacron程序只會處理位於cron目錄的程序,好比/etc/cron.monthly
    • 每一個cron目錄都有個時間戳文件,該文件位於/var/spool/anacron
    • anacron程序使用本身的時間表(一般位於/etc/anacrontab)來檢查做業目錄
    • anacron時間表的基本格式和cron時間表略有不一樣:
      • period delay identifier command

16.8 使用新的shell啓動腳本

  • 依照下列順序所找到的第一個文件會被運行,其他的文件會被忽略:
    • $HOME/.bash_profile
    • $HOME/.bash_login
    • $HOME/.profile

17. 建立函數

17.7 在命令行上使用函數

  • function divem { echo $[ $1 / $2 ]; }:採用單行方式定義函數
    • divem 100 5 :調用單行定義的函數
  • function doubleit { read -p "Enter value: " value; echo $[$value * 2 ]; }:須要注意的是得加分號,這樣才知道起止位置

    function multem {    echo [ 1 2 ]
    }

    • 也能夠像這樣採用多行定義的方式
    • . /home/rich/libraries/myfuncs:能夠在bashrc文件末尾加上你本身的函數庫

19. 初識sed和gawk

19.1 文本處理

  • sed options script file
    • -e script :在處理輸入時,將 script 中指定的命令添加到已有的命令中
    • -f file :在處理輸入時,將 file 中指定的命令添加到已有的命令中
    • -n :不產生命令輸出,使用 print 命令來完成輸出
    • 例如:
      • echo "This is a test" | sed 's/test/big test/'
      • sed 's/dog/cat/' data1.txt :不過不會修改文本文件的數據,只是顯示到STDOUT
      • sed -e 's/brown/green/; s/dog/cat/' data1.txt :使用多個命令須要用-e參數
      • sed -e ' :而後把命令一條一條輸進去
      • sed -f script1.sed data1.txt :也能夠把上述三條命令放進一個文件,經過-f參數指定這個文件,去處理data1.txt
  • gawk options program file
    • -F fs :指定行中劃分數據字段的字段分隔符
    • -f file :從指定的文件中讀取程序
    • -v var=value :定義gawk程序中的一個變量及其默認值
    • -mf N :指定要處理的數據文件中的最大字段數
    • -mr N :指定數據文件中的最大數據行數
    • -W keyword :指定gawk的兼容模式或警告等級
    • 例如:
      • gawk '{print "Hello World!"}' :對每行文本執行腳本
      • gawk '{print $1}' data2.txt:打印date2.txt文件中每行的第一個單詞,默認是空白字符或者製表符做爲分隔符
      • gawk -F: '{print $1}' /etc/passwd:-F指定字段分隔符
      • echo "My name is Rich" | gawk '{$4="Christine"; print $0}':要執行多個命令,只須要用」;」分隔
      • gawk '{:也能夠用此提示符一行一行的輸入
      • gawk -F: -f script2.gawk /etc/passwd:能夠把命令放到script.gawk文件中,經過-f參數運行
  • sed '2,$s/test/trial/' data4.txt 3gpw data4s.txt :轉義字符前加」\」
    • 3 :代表替換第幾處
    • g :替換全部匹配的文本
    • p :原先的內容要打印出來
    • w file :將替換的結果寫入文件中
    • 2,$ :第二行到後面的全部行
  • sed '/Samantha/s/bash/csh/' /etc/passwd:Samantha這裏能夠替換成正則表達式,因此整句只查找正則表達式匹配到的行
  • 0_1526906298982_8c89fd74-c2e1-4707-917a-d9677c30d758-image.png
    也能夠像這樣組合表達式
  • sed '3d' data6.txt:刪除第三行
  • sed '2,3d' data6.txt:刪除2~3行
  • sed '3,$d' data6.txt:刪除第三行開始之後的全部行
  • sed '/number 1/d' data6.txt:刪除出現number 1的行
  • sed '/1/,/3/d' data6.txt:第一個模式打開刪除功能,第二個模式關閉刪除功能,sed編輯器會刪除兩個指定行之間的全部內容,若是後面又匹配到1,又會打開刪除模式
  • echo "Test Line 2" | sed 'i\Test Line 1':-i參數在指定行前面插入一行
  • echo "Test Line 2" | sed 'a\Test Line 1':-a參數在指定行後面添加一行
  • sed '3i\> This is an inserted line.' data6.txt:這是一個將新行插入到第三行前面的例子
  • sed '$a\> This is a new line of text.' data6.txt附加到末尾
  • sed '3c\ This is a changed line of text.' data6.txt:-c參數指定修改模式,這裏修改第三行
  • sed '/number 3/c\ This is a changed line of text.' data6.txt:也能夠經過模式匹配的方式修改
  • sed '2,3c\ This is a new line of text.' data6.txt:也可使用區間地址,可是這一行會覆蓋二、3兩行
  • sed 'y/123/789/' data8.txt:1替換成9,2替換成8,3替換成9,直到替換完全部的字符
  • sed -n '/number 3/p' data6.txt:-p參數表打印模式,-n參數用來禁止輸出其餘行
  • 輸出以前打印
    0_1526908393422_77918f24-e501-4eb7-a376-4144570c9b8e-image.png
  • sed '=' data1.txt:」=」打印的會輸出行號
  • sed -n 'l' data9.txt:打印數據流中的文本和不可打印的ASCII字符
  • sed '1,2w test.txt' data6.txt:將數據流中的前兩行打印到文件中
  • sed '3r data12.txt' data6.txt:將data12.txt中的數據插入到data6.txt的第三行後面
  • sed '/number 2/r data12.txt' data6.txt:將data12中的數據插入到匹配行的後面
  • sed '$r data12.txt' data6.txt:插入到末尾
  • 0_1526909880112_0d833613-ca9e-4146-9486-6462d2889efa-image.png
    • 找到notice.std中包含LIST的那一行,並用data11.txt中的文本代替

20. 正則表達式

20.1 定義BRE模式

  • echo "This is a test 1" | sed -n '/test 1/p':p命令輸出匹配到的行,注意空格和其餘字符並無什麼區別
  • echo "This is a test" | gawk '/tes/{print $0}':print命令輸出匹配到的行,注意兩種寫法都區分大小寫,不用寫出完整單詞
  • 特殊字符:.*[]^${}\+?|()
    • sed -n '/\$/p' data2:使用特殊字符必須轉義
    • echo "3 / 2" | sed -n '/\//p':注意,使用正斜線也必須轉義
  • 錨字符
    • echo "Books are great" | sed -n '/^ Book/p':Book必須出如今行首才能匹配到
    • echo "This ^ is a test" | sed -n '/s ^ /p':脫字符放在其餘地方就變成普通字符了
    • echo "This is a good book" | sed -n '/book$/p':字符」$」指明數據行必須以該文本結尾
    • sed -n '/^ this is a test$/p' data4:會忽略那些不僅僅只包含這些文本的行
    • sed '/^ $/d' data5:刪除文本中的空白行
    • sed -n '/.at/p' data6:」.」匹配任意一個字符,若是沒有(如行首)則匹配失敗
    • sed -n '/[ch]at/p' data6:[ch]字符組取代」.」使通配符精確一點,不過必須有一個字符組中的字符被匹配到
    • sed -n ' /^ [0123456789][0123456789]$/p ' data8:匹配只出現兩個數字的一行
  • sed -n '/[^ ch]at/p' data6:在字符組的開頭加上脫字符,就成了了排除型字符組
  • sed -n '/^[0-9][c-h][a-ch-m]$/p' data8:單破折號表示linux字符集中得字符,即這樣能夠表示區間,最後一個區間表示a~c,h~m
  • 特殊字符

    這裏寫圖片描述

  • echo "ieeeek" | sed -n '/ie*k/p':字符後面放*,表示該字符要出現一次或屢次

  • echo "this is a regular pattern expression" | sed -n '/regular.*expression/p':.*的組合表示若干字符

20.2 擴展正則表達式

  • echo "bt" | gawk '/b[ae]?t/{print $0}':?表示字符組出現了一次或零次,另外,注意sed不支持擴展的正則表達式
  • echo "beeet" | gawk '/be+t/{print $0}':加號表示+前面的字符至少出現一次
  • echo "bet" | gawk --re-interval '/be{1}t/{print $0}':{}中的1表示e恰好出現了一次
  • echo "bt" | gawk --re-interval '/be{1,2}t/{print $0}':{}中的1,2表示至少出現一次,最多出現兩次
  • echo "The cat is asleep" | gawk '/cat|dog/{print $0}':管道容許匹配兩個模式中的任何一個
  • echo "Saturday" | gawk '/Sat(urday)?/{print $0}':()能對字符進行分組,即表示urday是一個總體

20.3 正則表達式實戰

相關文章
相關標籤/搜索