文章出處

shell 是什么

~ $ ls /bin/*sh
/bin/bash  /bin/csh  /bin/ksh  /bin/sh  /bin/tcsh  /bin/zsh

是什么

  • kernel shell
  • 命令解釋器,和 kernel 交互
  • 命令語言、程序設計語言

特性

  • 命令集
  • 膠水語言
  • 操作系統外殼接口

適合場景

  • 自動化簡單任務
  • 快速、簡單完成原型

劣勢

  • 移植性 grep --version wget--version
  • 執行效率
  • 組織性,結構性
  • 不支持面向對象特性

shell 特性

wget uc.cn -O uc.html 2>/dev/null || echo "Failed to get url"
  • 面向字符串
    • 元字符(metacharacter,分割字符串) space tab | < > & ( ) ;
    • 控制字符(control operator,分割命令) || & && ; ;; ( ) | |& <newline>
    • 轉義 ' " $ `` \
var=3+5
echo '$$ `uname` $var $((var))' 
echo "$$ \$ `uname` $var $((var))" 
  • 字符串展開
    • 利用元字符分割字符串
    • 如果字符串是用來給變量賦值,則不管它是否被雙引號包圍,都認為它被雙引號包圍
    • 大括號展開{};波浪線展開~、~-/、~+/ (不被單引號和雙引號包圍)
    • 參數和變量展開$USER $var $1 $@ $# ${var[i]} ${var:?value} ${var##value} ${var/pat/str};命令替換 ${cmd} `cmd`;算數展開 $((a+b)) (不被單引號包圍)
    • 單詞分割;路徑展開 (不被單引號和雙引號包圍)
    • 去掉字符串外面的引號 (如需重復以上流程使用 eval 聲明)
echo {a,b}cd{e,f}  ~  ~-/  `uname`  $(ls /bin/[kcz]sh)  $$  `ls /bin/e*`  /bin/?sh ${var}  $(($var))  $#
  • 字符串使用
    • 命令
      • 外部命令,命令名、選項、參數 ls -l /home
      • 內部命令,break continue : . echo eval exec exit export expr printf return set shift trap unset
    • 表達式 ((3+5))、[[ 4 > 5]]
    • 賦值 var=value
  • 常見語法
    • 簡單命令 cd ~
    • 管道 uname |grep linux
    • 命令序列 ; & || &&
    • 復合命令 () {} (()) [[]]
  • 流程控制選擇
if condition1; then
    statements
elif condition2; then
    statements
else
    statements
fi
  • 流程控制-循環
for var in one two three four five; do
    echo '$var is '$var
done

while until case select


shell 實戰

  • 對文件進行按行處理
cat in.txt |while read url; do
    echo "got $url"
done > out.txt
  • 生成配置包
tar -zcvf  update.`date '+%Y%m%d_%H%M%S'`.tar.gz somedir
  • 生成模板文件(其他格式化文本)
cat <<EO > index.html
<html>
<head>
<title></title>
</head>
hello $USER
your computer's name `hostname`
</html>
EO
  • 日志監控及定時處理
/usr/bin/find /home/dir -type f ! \( -name "*.bz2" -o -name "*.gz" \) -mmin +120 -exec bzip2 {} \; >/dev/null 2>&1
  • 去除文件重復(保留文件原有順序)
awk '!a[$0]++' in.txt > out.txt
  • 從文件中提取指定的內容
grep -Phio "(?<=\`uri=)[^\`]+" *.log |sort |uniq
grep -Pio "(?<='customizable': ')[^',]+" *.log  
`uri=http://13aaaa.com/html/PIC01/332190.html`wait=0.09`slow...
  • 文件非交互式編輯
sed -i 's/dispatch_rule/dispatch_rule = /g' in.txt
  • 計算
awk -F, '{sum+=$2} END{print sum}
  • 條件運算 && 、 ||
ps -ef |grep start_all.py |grep -v grep && exit 2  || python start_all.py
  • 變量替換、去除首尾字符
url='http://www_sina_com_cn/path/index.html'
echo ${url//_/.}
echo ${url#http://}
echo ${url%%/*}
  • 循環
for i in $(seq -w 0 23); do
    echo "log.8???_2014-10-15_$i"                                                                             
done
  • 查找
find . -type f |xargs -n 1000 grep -Pio -m 1 $key
find /nfs -size +10000k –xdev –exec ls –lh {} \;
find ~ -mtime +7 -name "*.log*" -exec rm -rf {} \;
  • 文件權限控制 r4 w2 x1 u(ser) g(roup) o(ther) a(ll)
chmod o+r filename
chmod 775 filename
chown user:user_group filename

shell的坑

  • 命令的返回狀態 0表示正常
if uname |grep -i linux; then
    echo 'you are using linux'
fi
  • 通配符擴展(和正則區別)
    * ? [set] [^set] {ba,c,k,z,tc}sh

  • 字符串比較,= != ;數字比較 -eq -ne -lt -le -gt -ge

if [ "$t1" != "$t2" -a $n1 -eq $n2 ] || [ $n3 -eq 100 ]; then
    ...
fi
  • crontab 任務列表不讀環境變量,執行腳本要絕對路徑
30 * * * * source /home/nemo/.bashrc; /home/nemo/somescript  > /dev/null
0-59   1-23   1-31   1-12   0-6  somescript
  • 重定向前后不可為同一文件
sort in.txt > in.txt

最佳實踐

  • 函數內部變量使用 local 聲明
func () {
    local var=hello;
}
  • 變量用花括號
echo echo ${BASH}_VERSION
echo ${10}
  • 字符串變量用雙引號
[ "$day" = yes ]
  • 一步到位
mkdir -p some/conf/{first,second/{third,forth}}
vi some/domains.conf
find . -name "dom*.conf" -exec vi {} \;
  • 其他
tar xvf -C ~ /nfs/some.tar.gz      # 減少移動文檔
cd ~ && tar xvf -C ~ /nfs/some.tar.gz # 鼓勵使用列表
使用 \ 進行長命令折行;
() {} 對命令分組執行
rm *.xml; rm some -r #避免 rm * -rf

附:

shell 內部特殊參數

字符 通用含義 示例及說明
* 位置變量列表,使用IFS第一個字符分開 fun 'hello world'
@ 位置變量列表
# 位置參數數目
? 最近一個前臺任務的返回狀態 $?
- 所有發送給shell的標志
$ 進程ID
! 最近被放到后臺執行的命令的進程ID
_ 前一個命令最后一個參數
0 shell、腳本名、函數名
1-9 shell、腳本、函數的位置參數 $2 ${10}

練習

已知 ls /tmp/* = /tmp/a /tmp/b /tmp/cVAR=/tmp/*,求以下命令的輸出:

  1. ls '$VAR'
  2. ls "$VAR"
  3. ls $VAR
  4. ls $VARa
  5. ls ${VAR}a
  6. eval ls "$VAR"

已知:/etc/hosts的內容為下:

192.168.1.11  oldboy11.etiantian.org
192.168.1.21  oldboy21.etiantian.org
192.168.1.31  oldboy31.etiantian.org

#192.168.1.111  oldboy111.etiantian.org

怎么才能在輸入IP后找到/etc/hosts里對應的唯一的hostname?


列出你最常用到的linux命令

grep awk sed find vi git  
cd ls echo cat cp mv wl tar

參考


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()