Bash 脚本学习

2021年9月2日 · 1282 字 · 3 分钟

工作和生活中用的电脑都是 ubuntu(18.04) 系统,时不时需要编写一些 Bash 脚本,目的当然是为了减少重复作业。为了避免每次都 临时低效 地检索,索性自己整理一下。互联网中资料是海量的,但是垃圾信息也越来越多了,感觉现在上网找答案都好难,到处都是广告,无脑转载,标题党……

$? $$ $# $@ $* $1

#!/bin/bash
ls
(( $? == 0 )) && echo "ok" || echo "error"

echo "I was called with $# parameters"
echo "My name is [$0]"
echo "My first parameter is [$1]"
echo "My second parameter is [$2]"
echo "All parameters are [$@]"
echo "All parameters are [$*]"
echo "PID is [$$]" 
  • $# 实际参数个数
  • $0 脚本自己的名字
  • $@ $* 所有参数
  • $1 $2 具体第几个参数
  • $$ PID

测试如下:

❯ bash ./temp.sh one 2 さん 四

I was called with 4 parameters
My name is [./temp.sh]
My first parameter is [one]
My second parameter is [2]
All parameters are [one 2 さん 四]
All parameters are [one 2 さん 四]
PID is [7958]

set

set 命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题.

## 脚本只要发生错误,就终止执行。
set -e 

## 脚本在头部加上它,遇到不存在的变量就会报错,并停止执行。 
set -u 

## 用来在运行结果之前,先输出执行的那一行命令。
set -x 

变量 && 数组

pai=3.1415
name="桃田賢斗"
number=9527
arr1=( $(ls) )             ## 数组声明 枚举
arr2=(1 2 3 4)             ## 数组声明 枚举
arr2+=("5" "6")            ## 增加元素
echo "$pai $name $number ${arr1[@]} ${arr2[@]}"

判断

if

字符串比较

l=abc
r="abc"
[[ $l == $r ]] && echo "$l == $r"
r="abcd"
[[ $l != $r ]] && echo "$l != $r"
l=abcde
[[ $l == *$r* ]] && echo "$l == *$r*"
#### 判断当前系统(OS)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # POSIX compatibility layer and Linux environment emulation for Windows
elif [[ "$OSTYPE" == "msys" ]]; then
        # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
elif [[ "$OSTYPE" == "win32" ]]; then
        # I'm not sure this can happen.
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
else
        # Unknown.
fi
## 判断某文件是否存在某个字符串, 单行书写,可以在 控制台执行
if grep -q "string" file; then echo ok; fi   

数字比较

one=1
two=2
(( $one >= $two )) && echo "$one >= $two"
(( $one <= $two )) && echo "$one <= $two"
(( $one == $two )) && echo "$one == $two"
(( $one > $two )) && echo "$one > $two"
(( $one < $two )) && echo "$one < $two"
## 判断 当前用户是否为 root,或者是否有 root 权限
if (( $EUID != 0 )); then
    echo "[ERROR] This script must be run as root!"
else 
    echo "ok, run as root!!!"    
fi

判断文件/目录是否存在

if [ -d "$dir" ]; then
  echo "have dir $dir"
fi

if [ -f "$file" ]; then echo "have file $file"; fi

NULL ?

[[ -z "$my_var" ]] && echo "\$my_var is NULL"

纯数字 ?

X=fasdf3213
echo $X | grep "[^0-9]" > /dev/null 2>&1
(( $? == 0 )) && echo "not number" || echo "number"

case

arr=(1 2 3 5 8 13)
for i in ${arr[@]}; do
    case $i in
        1|2|3) echo $i "=> 1|2|3";;
        4|5|6) echo $i "=> 4|5|6";;
        8) echo $i "=> 8";;
        *) echo $i "=> *";;
    esac
done

循环

for

#!/bin/bash
array=(1 2 3 4)             ## 数组声明 枚举

for i in "${array[@]}"; do  # 遍历数据
  echo $i
done

for i in {10..20}; do       ## 描述式数组
  echo $i
done

str="I am robot!"           ## 遍历字符串
for s in $str; do
  echo $s
done

while

i=0
while (( i < 10 )); do
  (( ++i )) && echo -en "$i "
done

echo "----------------------"

while :; do
  (( ++i ))
  (( i < 20 )) && echo -en "$i " || break
done

函数

main () {
  echo "$1"
  echo "hello world~"
  return 256      ## 最大返回 255
}

get_str () { str="Alice"; }

main "$@" "other arguments"
echo $?

get_str "$@"
echo $str

关键字

shift 迭代

while [[ "$#" -gt 0 ]]; do
    case $1 in
        -s|--stop) echo "need stop" ;;
        -l|--log) echo "show log" ;;
        *) echo "Unknown parameter passed: $1"; exit 1 ;;
    esac
    shift
done

read 命令行读取

read X && echo $X

IFS 分割符

old_IFS="$IFS"
IFS=:
echo "Please input some data seqarated by colons"
read x y z
IFS=$old_IFS
echo "x is $x; y is $y; z is $z"

trap 捕捉 signal

say_hi () {
  echo "おはよう"
}
trap 'say_hi' HUP

int i=0;
while (( i<10 )); do
  sleep 1
  (( ++i ))
  echo $i
done

exit 退出脚本

exit 0
echo "exit"       ## 不会执行

脚本

遍历当前目录

for i in *; do
  ls -l $i
done

array=( $(ls) )
for i in ${array[@]}; do
    ls -l $i
done

以“行”为单位读取文件,但是最后一行貌似不会读取

while read f
do
  case $f in
	hello)        echo English	;;
	howdy)        echo American	;;
	gday)         echo Australian	;;
	bonjour)      echo French	;;
	"guten tag")  echo German	;;
	*)		echo Unknown Language: $f ;;
   esac
done < myfile

ICON 反色处理

array=( $( ls | grep png) )
for png in ${array[@]}
do
    echo $png
    convert $png -channel RGB -negate $png.white.png
done

线路探测 ./xx.sh

line=`nslookup $1 | grep Address: | grep -o " .*" | sed 's/\ //g'`
line=`echo $line | sed 's/\ /,\ /g'`
echo $line
IFS=', ' read -r -a array <<< ${line}
for element in "${array[@]}"
do
    msg='{"cmd":"reqServer", "rServerAddr":"'${element}':'$2'", "pid":"'`date +"%s"`'", "seq":1, "sendTime":'1555379390294532000'}'
    echo "[C-->S] : $msg"
    echo -en '[C<--S] : ' 
    echo -n $msg | nc -u -w1 ${element} $2
    echo ''
done