随机
Enter 搜索 ↑↓ 切换 Esc 清空

shell-alert-box

命令

一键脚本

bash <(curl -sL gitee.com/meimolihan/cmdbox/raw/master/ops-script/shell-alert-box.sh) "第1行内容" "第2行内容"
bash <(curl -sL ../ops-script/shell-alert-box.sh) "第1行内容" "第2行内容"

效果预览

带警告词版

带警告词效果

无警告词版

无警告词效果

补充说明

warn_box 是一个用于在终端输出带有装饰边框的警告或提示框的 Bash 函数。该函数会自动计算最长内容行的宽度,根据内容是否包含中文字符自动调整内部宽度(中文/全角算 2 个字符,其它算 1 个字符),并绘制对应的上下横线、左右竖线以及角标字符。支持自定义上下留白行数,以及通过第一个纯数字参数指定留白数量。适用于 Bash 4+ 且环境支持 UTF-8 locale 的系统。

功能特点

参数说明

变量 默认值 说明
pad 1 上下留白行数;若第一个参数为纯数字,则使用该数值作为留白行数
lines - 要显示的内容行,作为剩余参数传入

函数调用格式:warn_box [留白行数] "第1行" "第2行" ...

用法示例

# 默认用法(1行上下留白,带警告词版)
warn_box  \
    '   我是第一行内容  ' \
    '   我是第二行内容  '

# 指定留白行数
warn_box 2  \
    '   内容行 1  ' \
    '   内容行 2  ' \
    '   内容行 3  '

# 无警告词版(洋红边框)
warn_box 0  \
    '   提示内容 1  ' \
    '   提示内容 2  '

# 两行留白 + 带警告词
warn_box 2  \
    '   警告信息测试  ' \
    '   这是第二行  '

注意事项

脚本源码

带警告词版(黄色边框 + “警告”)

cat > /tmp/warn_box.sh <<'EOF'
#!/bin/bash

__warn_box_width() {
    local s=$1 i c cp width=0
    local len=${#s}
    for ((i = 0; i < len; i++)); do
        c=${s:i:1}
        printf -v cp '%d' "'$c" 2>/dev/null || cp=63
        if (( (cp>=0x1100 && cp<=0x115F) || (cp>=0x2E80 && cp<=0x303E) || \
              (cp>=0x3041 && cp<=0x33FF) || (cp>=0x3400 && cp<=0x4DBF) || \
              (cp>=0x4E00 && cp<=0x9FFF) || (cp>=0xA000 && cp<=0xA4CF) || \
              (cp>=0xAC00 && cp<=0xD7A3) || (cp>=0xF900 && cp<=0xFAFF) || \
              (cp>=0xFE30 && cp<=0xFE6F) || (cp>=0xFF00 && cp<=0xFF60) || \
              (cp>=0xFFE0 && cp<=0xFFE6) || (cp>=0x1F300 && cp<=0x1F64F) )); then
            width=$((width + 2))
        else
            width=$((width + 1))
        fi
    done
    printf '%d' "$width"
}

warn_box() {
    local gl_huang=$'\033[38;5;11m'   # 黄色(边框 + “警告”)
    local gl_bai=$'\033[38;5;15m'     # 白色(内容)
    local reset=$'\033[0m'

    local pad=1
    if [[ $1 =~ ^[0-9]+$ ]]; then
        pad=$1
        shift
    fi
    local lines=("$@")
    local max=0 l w
    for l in "${lines[@]}"; do
        w=$(__warn_box_width "$l")
        (( w > max )) && max=$w
    done
    local W=$max
    (( W < 6 )) && W=6
    local top_bar bot_bar
    printf -v top_bar '%*s' $((W - 6)) ''
    top_bar=${top_bar// /─}
    printf -v bot_bar '%*s' "$W" ''
    bot_bar=${bot_bar// /─}
    printf '%s╭ 警告 %s╮%s\n' "$gl_huang" "$top_bar" "$reset"
    for ((i = 0; i < pad; i++)); do
        printf '%s│%*s│%s\n' "$gl_huang" "$W" "" "$reset"
    done
    for l in "${lines[@]}"; do
        w=$(__warn_box_width "$l")
        printf '%s│%s%s%s%*s%s│%s\n' \
            "$gl_huang" "$gl_bai" "$l" "$reset" \
            $((W - w)) "" "$gl_huang" "$reset"
    done
    for ((i = 0; i < pad; i++)); do
        printf '%s│%*s│%s\n' "$gl_huang" "$W" "" "$reset"
    done
    printf '%s╰%s╯%s\n' "$gl_huang" "$bot_bar" "$reset"
}

warn_box 0  \
    '   我是第一行内容  ' \
    '   我是第二行内容  '
EOF

sed -i 's/\r$//'/tmp/warn_box.sh
chmod +x /tmp/warn_box.sh
bash /tmp/warn_box.sh

无警告词版(洋红边框)

cat > /tmp/warn_box.sh <<'EOF'
#!/bin/bash

__warn_box_width() {
    local s=$1 i c cp width=0
    local len=${#s}
    for ((i = 0; i < len; i++)); do
        c=${s:i:1}
        printf -v cp '%d' "'$c" 2>/dev/null || cp=63
        if (( (cp>=0x1100 && cp<=0x115F) || (cp>=0x2E80 && cp<=0x303E) || \
              (cp>=0x3041 && cp<=0x33FF) || (cp>=0x3400 && cp<=0x4DBF) || \
              (cp>=0x4E00 && cp<=0x9FFF) || (cp>=0xA000 && cp<=0xA4CF) || \
              (cp>=0xAC00 && cp<=0xD7A3) || (cp>=0xF900 && cp<=0xFAFF) || \
              (cp>=0xFE30 && cp<=0xFE6F) || (cp>=0xFF00 && cp<=0xFF60) || \
              (cp>=0xFFE0 && cp<=0xFFE6) || (cp>=0x1F300 && cp<=0x1F64F) )); then
                width=$((width + 2))
            else
                width=$((width + 1))
            fi
    done
    printf '%d' "$width"
}

warn_box() {
    local gl_bai=$'\033[38;5;15m'   # 白色(内容)
    local gl_zi=$'\033[38;5;13m'    # 洋红(边框)
    local reset=$'\033[0m'

    local pad=1
    if [[ $1 =~ ^[0-9]+$ ]]; then
        pad=$1
        shift
    fi
    local lines=("$@")
    local max=0 l w
    for l in "${lines[@]}"; do
        w=$(__warn_box_width "$l")
        (( w > max )) && max=$w
    done
    local W=$max
    (( W < 1 )) && W=1
    local bar
    printf -v bar '%*s' "$W" ''
    bar=${bar// /─}
    printf '%s╭%s╮%s\n' "$gl_zi" "$bar" "$reset"
    for ((i = 0; i < pad; i++)); do
        printf '%s│%*s│%s\n' "$gl_zi" "$W" "" "$reset"
    done
    for l in "${lines[@]}"; do
        w=$(__warn_box_width "$l")
        printf '%s│%s%s%s%*s%s│%s\n' \
            "$gl_zi" "$gl_bai" "$l" "$reset" \
            $((W - w)) "" "$gl_zi" "$reset"
    done
    for ((i = 0; i < pad; i++)); do
        printf '%s│%*s│%s\n' "$gl_zi" "$W" "" "$reset"
    done
    printf '%s╰%s╯%s\n' "$gl_zi" "$bar" "$reset"
}

warn_box 0  \
    '   我是第一行内容  ' \
    '   我是第二行内容  '
EOF

sed -i 's/\r$//'/tmp/warn_box.sh
chmod +x /tmp/warn_box.sh
bash /tmp/warn_box.sh

创建本地脚本

new_script="new_test.sh"

cat > "$new_script" << 'EOF'
# 粘贴脚本源码

EOF

# 保留本地脚本,去掉 rm -f "$new_script"
chmod +x "$new_script" && ./"$new_script" && rm -f "$new_script"