0%

Bash 中的特殊符号:全面解析与实用指南

Bash shell 中有的特殊符号是实现复杂命令和脚本逻辑的基础,它们赋予了 Shell 强大的文本处理和流程控制能力。理解这些符号的含义和用法,能帮助你写出更简洁、高效的命令和脚本。

引号类符号:控制字符解析

单引号 ''

  • 作用强引用,单引号内的所有字符(包括特殊符号)都被视为普通字符,无特殊含义。
  • 适用场景:需要原样输出包含特殊符号(如 $!空格)的字符串。

示例

1
2
3
name="Alice"
echo 'Hello $name' # 输出:Hello $name($name 不解析为变量)
echo '当前目录:$(pwd)' # 输出:当前目录:$(pwd)(命令不执行)

双引号 ""

  • 作用:弱引用,双引号内大部分字符视为普通字符,但保留以下特殊符号的含义:
    • $:引用变量(如 $name
    • `:执行命令(如date``)
    • \:转义符(如 \" 表示输出双引号)
  • 适用场景:需要保留变量和命令执行结果,同时避免空格等字符被拆分。

示例

阅读全文 »

Redis intset(整数集合)实现详解(基于 6.0.10 版本)

intset(整数集合)是 Redis 中 Set 类型的底层实现之一,专门用于存储整数值元素(如 int16_t、int32_t、int64_t)。当 Set 中仅包含整数且元素数量较少时,Redis 会选择 intset 而非哈希表(hashtable),以节省内存空间。

intset 的核心设计目标

  • 内存高效:相比哈希表(需存储键值对和指针),intset 以紧凑数组形式存储整数,无冗余开销。
  • 类型灵活:支持不同长度的整数(16 位、32 位、64 位),并能自动升级编码以容纳更大的整数。
  • 有序性:元素在数组中按升序排列,支持快速查找(二分查找)。

intset 的结构体设计

intset 的结构体定义简洁高效,源码如下:

1
2
3
4
5
typedef struct intset {
uint32_t encoding; // 编码方式(决定元素的类型和长度)
uint32_t length; // 元素数量
int8_t contents[]; // 柔性数组,存储整数元素(实际类型由 encoding 决定)
} intset;

各字段详解:

阅读全文 »

Redis 跳跃表(Skiplist)实现详解(基于 6.0.10 版本)

跳跃表(Skiplist)是一种高效的有序数据结构,通过在节点中维护多层指针,实现快速查找、插入和删除操作(平均时间复杂度 O (logN))。Redis 中,跳跃表是有序集合(ZSet)的底层实现之一(当 ZSet 元素数量多或元素较大时使用,替代 ziplist)。本文结合 Redis 源码中的结构体,详解跳跃表的设计与工作原理。

跳跃表的核心作用

ZSet 需要支持按分值(score)排序快速范围查询(如 ZRANGEZREVRANGE),跳跃表相比其他结构(如平衡树)的优势:

  • 实现简单:无需像红黑树那样维护复杂的旋转平衡逻辑。
  • 性能均衡:查找、插入、删除的平均时间复杂度均为 O (logN),且常数因子小。
  • 适合范围查询:通过层级指针可直接定位到范围起点,高效遍历区间元素。

跳跃表的结构体设计

Redis 中跳跃表由两个核心结构体组成:zskiplistNode(节点)和 zskiplist(表本身),定义如下(简化自源码):

跳跃表节点(zskiplistNode

1
2
3
4
5
6
7
8
9
typedef struct zskiplistNode {
sds ele; // 存储的元素(字符串,ZSet 中的 member)
double score; // 分值,用于排序(ZSet 中按 score 排序)
struct zskiplistNode *backward; // 后退指针(仅指向当前节点的前一个节点,用于反向遍历)
struct zskiplistLevel { // 层级数组(每个层级包含前进指针和跨度)
struct zskiplistNode *forward; // 前进指针(指向同一层级的下一个节点)
unsigned long span; // 跨度(当前节点到 forward 指向节点的"距离",用于计算排名)
} level[]; // 柔性数组(层级数量动态分配,每层独立维护指针)
} zskiplistNode;
关键字段解析:
  • ele:ZSet 中的成员(member),是一个字符串(sds 类型),具有唯一性(ZSet 不允许重复 member)。
  • score:成员对应的分值,ZSet 按 score 升序排序(相同 score 的节点按 ele 字典序排序)。
  • backward:后退指针,仅用于反向遍历(如 ZREVRANGE),指向当前节点的前一个节点(类似双向链表的 prev 指针),但仅在最底层有效。
  • level[]:层级数组,是跳跃表 “跳跃” 特性的核心:
    • 每个节点的层级数量是随机生成的(通常 1-64 层,Redis 中最大层级为 64)。
    • 层级越高,前进指针跨越的节点越多,查询时可快速 “跳过” 无关节点。

跳跃表本身(zskiplist

阅读全文 »

Shell 重定向详解:从标准流到 tee 命令的完整指南

在 Shell 中,输入输出重定向是控制命令数据流的核心机制,通过灵活处理标准输入(stdin)、标准输出(stdout)和标准错误(stderr),可以实现日志记录、错误屏蔽、批量处理等多种功能。本文将系统讲解重定向的原理、用法及 tee 命令的应用。

标准流与文件描述符

Shell 中所有命令的输入输出都基于三个标准流,每个流对应一个文件描述符(用于在系统中标识流):

标准流 功能描述 文件描述符 默认设备
stdin 标准输入(命令读取数据) 0 键盘
stdout 标准输出(命令正常输出) 1 终端屏幕
stderr 标准错误(命令错误输出) 2 终端屏幕

这些流可以被重定向到文件、设备或其他命令,改变数据的默认流向。

输入重定向(<

输入重定向用于将命令的输入来源从默认的键盘改为指定文件,语法为:
命令 < 输入文件

常用场景

  • 批量输入数据(如给 mail 命令提供邮件内容);
  • 替代管道传递文件内容(等价于 cat 输入文件 | 命令)。

示例

阅读全文 »

MySQL 忘记密码解决方案:重置密码的完整步骤

忘记 MySQL 密码是常见问题,可通过跳过权限验证的方式重置密码。以下是针对不同操作系统的详细步骤,以及密码策略的调整方法。

通用重置步骤(以 MySQL 8.0 为例)

停止 MySQL 服务

首先确保 MySQL 服务已停止,否则无法进行后续操作:

1
2
3
4
5
# Linux/Mac 系统
sudo systemctl stop mysql # 或 mysql.server stop(取决于安装方式)

# Windows 系统(管理员命令提示符)
net stop mysql

跳过权限验证启动 MySQL

以跳过权限表的方式启动 MySQL,此时登录无需密码:

1
2
3
4
5
# Linux/Mac 系统(后台启动,日志输出到文件)
sudo mysqld --skip-grant-tables --user=mysql > /dev/null 2>&1 &

# Windows 系统(需切换到 MySQL 的 bin 目录,如 D:\mysql-8.0\bin)
mysqld --skip-grant-tables

注意

  • 执行此命令时,确保 MySQL 服务已完全停止,否则会提示 “端口被占用”。
  • 该模式下 MySQL 安全性极低,重置密码后需立即关闭并重启服务。

无密码登录 MySQL

新开一个终端 / 命令提示符窗口,直接登录 MySQL(无需输入密码):

1
mysql -u root  # 直接回车,无需输入密码

刷新权限并重置密码

登录后,需先刷新权限表,再修改 root 密码:

阅读全文 »