Bash 脚本教程
Bash 基础语法
定义变量(变量名和等号之间不能有空格)
a=10
Bash 数组
定义数组
array=(1 2 3)
以命令返回结果定义数组
files=( $(ls) )
获得数组中的某个元素
a=${array[0]}
获得数组的长度
length=${#array[@]}
Bash 运算
自增
c=$((++c))
加法
b=$[$a+1]
Bash 判断语句
单中括号
判断大小
[ $COMP_CWORD -ge 7 ]
双中括号 (注意两侧空格)
正则匹配(变量)
[[ "$pre" =~ "-h" ]]
取反(不是
!~)
[[ ! "$pre" =~ "-h" ]]
正则匹配(数组)
[[ "${COMP_WORDS[@]}" =~ "-s" ]]
逻辑判断
[[ "${COMP_WORDS[@]}" =~ "-s" || "${COMP_WORDS[@]}" =~ "--sequential" ]]
Bash 循环语句
for 循环
for (( i=0; i<${#array[@]}; i++ ))
do
echo ${array[i]}
done
while 循环
while [ $c -lt $COMP_CWORD ]
do
c=$((++c))
done
Bash 变量替换
使用下述命令可以实现字符串的变量替换:
${string/substring/replacement} # 替换第一个匹配项
${string//substring/replacement} # 替换全部匹配项
具体效果如下所示:
EXEC=/opt/vasp/bin/vasp_std
${EXEC/vasp_std/vasp_gam} => /opt/vasp/bin/vasp_gam
Note
当省略第二个 / 时,将会把匹配到的字符串从变量中删除
例如,我们有一个变量 user
user=root:x:0:0:root:/root:/bin/bash
使用下述命令会发生字符串的删除;
> ${user/r*t}
> :/bin/bash
> ${user//r\*t}
> :/bin/bash
> ${user//r??t}
> :x:0:0::/:/bin/bash
> ${user/r??t}
> :x:0:0:root:/root:/bin/bash
Bash 字符串删除
假设我们定义了一个变量 file
file=/dir1/dir2/dir3/my.file.txt
我们可用 ${var#}/${var%} 来进行字符串删除获得不同的值:
> ${file#_/}
> dir1/dir2/dir3/my.file.txt
> ${file##_/}
> my.file.txt
> ${file#\*.}
> file.txt
> ${file##_.}
> txt
> ${file%/_}
> /dir1/dir2/dir3
> ${file%%/\*}
> (空值)
> ${file%.\_}
> /dir1/dir2/dir3/my.file
> ${file%%.\_}
> /dir1/dir2/dir3/my
Bash 函数
将 ls 的结果放到 files 数组中
_files () {
local c=0
for file in `ls`
do
files[$c]=$file
c=$((++c))
done
echo ${files[@]}
}
获取函数的返回值
files=( $(_files) )
mkdir 命令
构建多级目录 (-p 参数)
mkdir -p /opt/intel/oneapi/**
find 命令
通过管道传送多个命令 (显示指明
bash -c)
find DIR -iname '*.gro' -exec bash -c 'echo -n "{} "; grep UNL {} | wc -l' \;
查找重复文件
find -not -empty -type f -printf "%s\n" | sort -rn | uniq -d | xargs -I{} -n1 find -type f -size {}c -print0 | xargs -0 md5sum | sort | uniq -w32 --all-repeated=separate
xargs 命令
参数替换(-I 选项)
ls | shuf -n 50 | xargs -I {} cp {} DIR
其中,shuf 命令随机选择 N 个文件
awk 命令
条件语句
awk -F, '{if($5>2000){print $0}}' file
sort 命令
先将第一列倒排,再将第三列以数值格式倒排
sort -k 1,1r -k 3,3nr content
grep 命令
多行匹配时去掉分组符号”-”
grep -A2 pattern --no-group-separator
Linux 自定义命令补全
实现 Linux 系统下自定义命令的补全需要借助 bash-completion,它是对 bash 补全功能的增强,可以实现对参数和包名的补全。
默认安装位置在 /etc/bash_completion (/usr/share/bash-completion/completions则是一些工具的补全实现,可作为参考),如果没有安装,可以借助 apt 工具进行安装。
apt install bash-completion
自动补全脚本编写
实现自定义命令的补全主要借助两个命令(complete 和 compgen)以及几个环境变量(COMPREPLY,COMP_WORDS 和 COMP_CWORD),下面对他们的一些用法进行说明。
complete 命令
用自定义函数(_gvasp)对自定义命令(gvasp)进行补全
complete -F _gvasp gvasp
取消自动添加空格
complete -o -F _gvasp gvasp
compgen 命令
对 cur 字符串从 opts 中进行补全
compgen -W "$opts" -- $cur
当未找到匹配项时,以 bash 自带的补全进行替换
compgen -o default -W "$opts" -- $cur
重要环境变量
COMP_CWORD表示当前光标所在的索引COMP_WORDS当前命令行所有单词组成的数组COMPREPLY从该数组变量中产生后续的命令补全
简单实现
_gvasp_submit() {
local cur opts
COMPREPLY=()
pre=${COMP_WORDS[COMP_CWORD-1]}
cur=${COMP_WORDS[COMP_CWORD]}
if [[ "$pre" =~ "-" ]]; then
opts=""
else
opts="opt con-TS chg wf dos freq md stm neb dimer -h --help"
fi
COMPREPLY=( $( compgen -W "$opts" -- $cur ) )
}
定义好的 bash-completion 脚本在 ~/.bashrc 中定义并通过 source 命令执行即可。