shell常用方法总结

特殊符号说明

符号 说明
$$ Shell本身的PID(ProcessID,即脚本运行的当前进程ID号)
$! Shell最后运行的后台Process的PID(后台运行的最后一个进程的[进程ID]
$? 最后运行的命令的结束代码(返回值)即执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$$ 显示shell使用的当前选项,与set命令功能相同
$* 所有参数列表。如”$*“用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数,此选项参数可超过9个。
$@ 所有参数列表。如”$@“用「”」括起来的情况、以”$1” “2 “ … “ 2” … “2”…”n” 的形式输出所有参数。
$* 跟$@类似,但是可以当作数组用
$# 添加到Shell的参数个数
$0 Shell本身的文件名
$1~$n 添加到Shell的各参数值。$1是第1参数、$2是第2参数…

比较运算

文件比较运算符

操作符 解释 示例
-e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
-b filename 如果 filename 存在且为块文件则为真
-d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
-c filename 如果filename存在且为字符型特殊文件则为真。 [ -c /var/mytmp]
-x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
-s filename 若文件ilename存在且至少有一个字符则为真
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真

字符串比较

操作符 解释 示例
-z string 如果 string 长度为零,则为真 [ -z “$myvar” ]
-n string 如果 string 长度非零,则为真 [ -n “$myvar” ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ “$myvar” = “one two three” ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ “$myvar” != “one two three” ]

数值比较

操作符 解释 示例
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]

|| 与 &&

&&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功&&那么执行这个命令”

||则与&&相反。如果||左边的命令(command1)未执行成功,那么就执行||右边的命令(command2);或者换句话说,“如果这个命令执行失败了||那么就执行这个命令。

脚本内容 输出
app() {
return 0
}
app && echo “3”
3
app() {
return 1
}
app || echo “3”
3

变量

操作符 解释 是否修改原始value
${value:-word} 当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值. NO
${value:=word} 若变量未定义或者值为空时,在返回word的值的同时将word赋值给value YES
${value:?message} 若变量以赋值的话,正常替换.否则将消息message送到标准错误输出
(若此替换出现在Shell程序中,那么该程序将终止运行)
NO
${value:+word} 若变量以赋值的话,其值才用word替换,否则不进行任何替换 NO
${value:offset} 从变量中提取子串,这里offset和length可以是算术表达式. NO
${#value} 变量的字符个数 NO
${value#pattern}
${value##pattern}
去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配
#与##的区别在于一个是最短匹配模式,一个是最长匹配模式.
NO
${value%pattern}
${value%%pattern}
去掉value中从尾部与pattern相匹配的部分,%与%%的区别与#与##一样 NO
${value/pattern/string}
${value//pattern/string}
进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区别与上同 NO

判定变量是否是数值

使用-z "${p//[0-9]/}" 判定变量是否是数值。原理为//[0-9]/ 是一种字符串替换方式,将 p 变量中的数字(0到9)全部替换为空字符串,然后再判断(-z )替换后的字符串是否为空。如果 p 是空字符串或者只由数字组成,则条件为真,返回 true;

其中${p//[0-9]/}没有修改原始变量 p 的值,因为在 shell 中使用类似的字符串操作符都是返回一个新的字符串,而没有修改原字符串的值.

示例如下:

1
2
3
4
5
6
p="1234"
if [ -z "${p//[0-9]/}" ]; then
echo "num=$p"
else
echo "string"
fi

数组

  • 读取数组 格式是:${array_name[index]}
  • 获取数组中的所有元素:使用@ 或 * 可以获取数组中的所有元素,
  • 获取数组的长度:获取数组长度的方法与获取字符串长度的方法相同

    遍历循环方法

    有3中方法遍历

    标准的for循环

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash
    echo "创建一个数组"
    array=( "A" B C D 1 2 3 "4" )

    #${#array[@]}获取数组长度用于循环
    for(( i=0;i<${#array[@]};i++)) do
    echo ${array[i]};
    done;

    for … in循环方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/bin/bash
    echo "创建一个数组"
    array=( "A" B C D 1 2 3 "4" )

    #也可以写成for element in ${array[*]}
    for element in ${array[@]}
    do
    echo $element
    done

    While循环法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash
    echo "创建一个数组"
    array=( "A" B C D 1 2 3 "4" )

    i=0
    #当变量(下标)小于数组长度时进入循环体
    while [ $i -lt ${#array[@]} ]
    do
    echo ${array[$i]}
    #按下标打印数组元素
    let i++
    done

将文件内容加载到数组中

文件的内容以空格为分隔每个数组元素

1
2
3
4
5
6
7
8
#!/bin/bash

file="./test_file.log"
array=(`cat ${file} `)
for line in ${array[@]}
do
echo "line=${line}"
done

test_file.log内容如下

1
2
3
aaa mm
bbbb cccc
ddd2

结果输出为

1
2
3
4
5
line=aaa
line=mm
line=bbbb
line=cccc
line=ddd2

实用语句

  • 杀掉除今天和pid=1的所有/bin/bash进程

    1
    ps -eo pid,lstart,cmd |grep "/bin/bash" |grep -v "$(date +'%b %e')" |grep -v '^ *1 ' |awk '{print $1}' |xargs -r kill -9
  • 遍历目录下所有文件

    1
    2
    3
    4
    5
    6
    7
    directory="./example_directory"  # Replace with your directory path

    for file in "$directory"/*; do
    if [ -f "$file" ]; then
    echo "File: $file"
    fi
    done
  • 遍历多行变量的每一行数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 定义一个多行变量
    multi_line="apple
    banana
    orange"

    # 使用while循环遍历多行变量的每一行数据
    echo "遍历多行变量的每一行数据:"
    echo "$multi_line" | while IFS= read -r line; do
    echo "$line"
    done
  • 按行读取文件,并处理每行的IP地址

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 文件路径
    file="/path/to/file.txt"
    # 初始化计数器
    count=0

    # IFS为指定分隔符(Internal Field Separator)
    while IFS= read -r ip; do
    echo "处理IP地址: $ip"
    # 计数器递增
    count=$((count+1))
    done < "$file"
  • 当执行ssh 命令时while read文件会执行一次就中断,可以使用下面的方式循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/bin/bash
    # 文件路径
    file="./m"

    cmd="ps -eLF|grep mmm |grep -v \"grep\" |grep -v \"ppp\" |wc -l"
    #cmd="ps -ef|grep mmm|grep -v \"grep\" |grep -v \"ppp\" |awk '{print \$2}'"
    ips=$(cat ${file})
    for ip in $ips
    do
    ret=`ssh root@"${ip}" "${cmd}"`
    echo "处理IP地址:${ip}, thread=${ret}"
    # 计数器递增
    #count=$((count+1))
    done
  • 数字对齐,不足补0

    1
    2
    3
    4
    5
    6
    #!/bin/bash

    for ((i=1; i<=400; i++)); do
    x="$(printf "%03d\n" $i) "
    echo ${x}
    done

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!