chaterm

shell-scripting

Bash Shell 脚本编写

chaterm 57 12 Updated 7mo ago
GitHub

Install

npx skillscat add chaterm/terminal-skills/shell-scripting

Install via the SkillsCat registry.

About this skill

This skill enables writing, debugging, and maintaining Bash shell scripts for automation tasks. It solves the problem of manual repetitive operations by enabling scripted workflows. Use it when automating file manipulation, system monitoring, or data processing tasks in Linux environments.

SKILL.md

Shell 脚本编写

概述

Bash 脚本编写、调试、最佳实践等技能。

基础语法

脚本结构

#!/bin/bash
# 脚本描述
# Author: name
# Date: 2024-01-01

set -euo pipefail                   # 严格模式

# 变量定义
VAR="value"
readonly CONST="constant"

# 主逻辑
main() {
    echo "Hello, World!"
}

main "$@"

变量

# 定义变量
name="value"
name='literal value'                # 不解析变量

# 使用变量
echo $name
echo ${name}
echo "${name}_suffix"

# 默认值
${var:-default}                     # 未设置时使用默认值
${var:=default}                     # 未设置时赋值并使用
${var:+value}                       # 已设置时使用 value
${var:?error message}               # 未设置时报错

# 字符串操作
${#var}                             # 长度
${var:0:5}                          # 子串
${var#pattern}                      # 删除前缀
${var%pattern}                      # 删除后缀
${var/old/new}                      # 替换

数组

# 定义数组
arr=(a b c d)
arr[0]="first"

# 访问数组
${arr[0]}                           # 第一个元素
${arr[@]}                           # 所有元素
${#arr[@]}                          # 数组长度
${!arr[@]}                          # 所有索引

# 遍历数组
for item in "${arr[@]}"; do
    echo "$item"
done

流程控制

条件判断

# if 语句
if [[ condition ]]; then
    commands
elif [[ condition ]]; then
    commands
else
    commands
fi

# 条件表达式
[[ -f file ]]                       # 文件存在
[[ -d dir ]]                        # 目录存在
[[ -z "$var" ]]                     # 变量为空
[[ -n "$var" ]]                     # 变量非空
[[ "$a" == "$b" ]]                  # 字符串相等
[[ "$a" != "$b" ]]                  # 字符串不等
[[ $a -eq $b ]]                     # 数字相等
[[ $a -lt $b ]]                     # 小于
[[ $a -gt $b ]]                     # 大于

# 逻辑运算
[[ cond1 && cond2 ]]                # 与
[[ cond1 || cond2 ]]                # 或
[[ ! cond ]]                        # 非

循环

# for 循环
for i in 1 2 3 4 5; do
    echo $i
done

for i in {1..10}; do
    echo $i
done

for ((i=0; i<10; i++)); do
    echo $i
done

for file in *.txt; do
    echo "$file"
done

# while 循环
while [[ condition ]]; do
    commands
done

# 读取文件
while IFS= read -r line; do
    echo "$line"
done < file.txt

# until 循环
until [[ condition ]]; do
    commands
done

case 语句

case "$var" in
    pattern1)
        commands
        ;;
    pattern2|pattern3)
        commands
        ;;
    *)
        default commands
        ;;
esac

函数

定义函数

# 方式1
function_name() {
    local var="local variable"
    echo "Arguments: $@"
    echo "First arg: $1"
    echo "Arg count: $#"
    return 0
}

# 方式2
function function_name {
    commands
}

# 调用函数
function_name arg1 arg2

# 获取返回值
result=$(function_name)

常用函数模板

# 日志函数
log() {
    local level=$1
    shift
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*"
}

log INFO "This is info message"
log ERROR "This is error message"

# 错误处理
die() {
    echo "ERROR: $*" >&2
    exit 1
}

# 确认函数
confirm() {
    read -p "$1 [y/N] " response
    [[ "$response" =~ ^[Yy]$ ]]
}

if confirm "Continue?"; then
    echo "Proceeding..."
fi

输入输出

读取输入

# 读取用户输入
read -p "Enter name: " name
read -sp "Enter password: " password   # 隐藏输入
read -t 10 -p "Quick! " answer          # 超时

# 读取文件
while IFS= read -r line; do
    echo "$line"
done < file.txt

重定向

# 输出重定向
command > file                      # 覆盖
command >> file                     # 追加
command 2> error.log                # 错误输出
command > file 2>&1                 # 合并输出
command &> file                     # 同上

# 输入重定向
command < file

# Here Document
cat << EOF
多行文本
变量: $var
EOF

cat << 'EOF'                        # 不解析变量
原始文本
EOF

调试技巧

调试选项

# 启用调试
set -x                              # 打印执行的命令
set -v                              # 打印读取的行
set -e                              # 出错即退出
set -u                              # 未定义变量报错
set -o pipefail                     # 管道错误传递

# 组合使用
set -euxo pipefail

# 调试特定部分
set -x
# 调试代码
set +x

调试工具

# 语法检查
bash -n script.sh

# 调试运行
bash -x script.sh

# shellcheck 静态分析
shellcheck script.sh

最佳实践

脚本模板

#!/bin/bash
#
# Script: script_name.sh
# Description: Brief description
# Author: Your Name
# Date: 2024-01-01
#

set -euo pipefail

# Constants
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"

# Logging
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
error() { echo "[ERROR] $*" >&2; }
die() { error "$*"; exit 1; }

# Usage
usage() {
    cat << EOF
Usage: $SCRIPT_NAME [options] <arguments>

Options:
    -h, --help      Show this help message
    -v, --verbose   Enable verbose mode

Examples:
    $SCRIPT_NAME -v input.txt
EOF
}

# Parse arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                usage
                exit 0
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            *)
                ARGS+=("$1")
                shift
                ;;
        esac
    done
}

# Main
main() {
    parse_args "$@"
    
    # Your logic here
    log "Starting $SCRIPT_NAME"
}

main "$@"

故障排查

问题 解决方法
语法错误 bash -n script.sh 检查
变量未定义 使用 set -u${var:-}
空格问题 变量加引号 "$var"
管道错误被忽略 使用 set -o pipefail
调试困难 使用 set -xshellcheck