尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

fish shell 的 `string sub` 子串提取命令完全指南:索引规则、边界处理与实战用法

fish shell 的 `string sub` 子串提取命令完全指南:索引规则、边界处理与实战用法 CLI开发工具【免费下载链接】fish-shellThe user-friendly command line shell.项目地址https://gitcode.com/GitHub_Trending/fi/fish-shell点击查看免费下载string sub是 fish shell 内建string命令中负责截取子串的子命令它以 1-based 索引、支持正负双向定位正数从字符串头部数、负数从尾部数并用--start/--end/--length三组选项灵活划定区间。读完本文你将完整掌握string sub的语法、索引换算规则、边界值行为、退出状态语义以及在 fish 脚本与补全定义中按列解析输出、裁剪前缀/后缀的典型实战写法。本文以 string sub 官方文档 为骨架并结合仓库内 Rust 实现、集成测试 与各补全脚本中的真实用法进行印证与扩充。一、命令概览它是谁用在哪string sub是string内建命令家族的一员。在 fish 中string是一系列字符串处理子命令的总入口collect、escape、join、length、match、pad、repeat、replace、shorten、split、sub、trim、upper等其总览见 string 命令文档。从源码看string内建在 src/builtins/string.rs 中按子命令名分发其中sub sub::Sub::default().run(parser, streams, args)见 src/builtins/string.rs#L328即把请求转交给Sub结构体的实现。与cut、sed等外部工具不同string sub是纯内建实现它不读取文件而是处理命令行参数或 stdin 中的每一行字符串不依赖外部进程因而在循环与补全中被高频调用也不会产生明显的进程开销。二、语法与选项全解string sub的完整语法如下摘自 string-sub.rst 的 Synopsis 段string sub [(-s | --start) START] [(-e | --end) END] [(-l | --length) LENGTH] [-q | --quiet] [STRING ...]各选项含义与约束汇总如下表选项长选项参数含义与约束-s--start整数子串起始位置1-based正数相对字符串开头负数相对字符串结尾默认值为 1不允许为 0-e--end整数子串结束位置1-based 且为包含端点正数相对开头、负数相对结尾不允许为 0与--length互斥-l--length整数子串长度字符个数必须为非负整数不允许为负数与--end互斥-q--quiet无静默模式不输出结果仅以退出状态表达是否执行了至少一次截取在 src/builtins/string/sub.rs 中选项定义清晰可见const LONG_OPTIONS: static [WOptionstatic] [ wopt(L!(length), RequiredArgument, l), wopt(L!(start), RequiredArgument, s), wopt(L!(end), RequiredArgument, e), wopt(L!(quiet), NoArgument, q), ]; const SHORT_OPTIONS: static wstr L!(l:qs:e:);即-l、-s、-e均需要参数-q不需要参数。任何数值参数都会经过parse_arg_number解析见 src/builtins/string.rs 中的StringSubCommand::parse_arg_number解析失败会报错并以状态码 2STATUS_INVALID_ARGS退出。几个容易踩的硬性约束--length与--end互斥两者同时给出时命令直接报错。该检查在Sub::handle的开头完成见 src/builtins/string/sub.rs#L63-L71错误信息为string sub: invalid option combination, --end and --length are mutually exclusive测试用例见 tests/checks/string.fish#L255-L256。--start/--end不能是 0起始、结束位置使用NonZeroI64存储0 被拒绝报Invalid start value 0/Invalid end value 0见 tests/checks/string.fish#L85-L86 与 tests/checks/string.fish#L234-L235。--length不能为负长度最终转换为usize负数转换失败报Invalid length value -1见 tests/checks/string.fish#L222-L223。三、索引语义深入解析正负号与换算规则这是string sub最核心、也最容易被混淆的部分。官方文档的原始表述是The start/end of the substring can be specified with-s/-eor--start/--endfollowed by a 1-based index value. Positive index values are relative to the start of the string and negative index values are relative to the end of the string. The default start value is 1.也就是说所有索引都是 1-based正数从字符串开头数起负数从字符串结尾数起。下面用abcde长度为 5为例给出索引到实际切片的换算表索引值含义换算为 0-based 位置Python/切片思维实际效果1第一个字符0从a开始5最后一个字符4从e开始-1倒数第 1 个4len - 1从e开始-2倒数第 2 个3len - 2从d开始-5倒数第 5 个0从a开始-6超出范围0被 clamp 到 0仍从开头开始这一换算逻辑在 src/builtins/string/sub.rs 中体现为两段计算start 的换算arg为当前字符串len为其长度let start: usize match self.start.map(i64::from).unwrap_or_default() { n 1.. n as usize - 1, // 正数1-based 转 0-based 0 0, // 理论上不可达0 已被拒绝 n arg.len().saturating_sub(n.unsigned_abs() as usize), // 负数从尾部倒数 }.clamp(0, arg.len());end 的换算与长度计算let count { let n self.end.map(|e| match i64::from(e) { n 1.. n as usize, // 正数 end直接作为切到第 n 个字符之后 n arg.len().saturating_sub(n.unsigned_abs() as usize), // 负数 end从尾部倒数 }).map(|n| n.saturating_sub(start)); // 区间长度 end - start self.length.or(n).unwrap_or(arg.len()) // 三选一length end 推导 整串长度 };输出时再做一次兜底arg[start..usize::min(start count, arg.len())]保证即使start count越界也只会安全截断到字符串末尾不会 panic。三者的优先级关系实际输出长度按以下顺序确定指定了--length→ 用length否则指定了--end→ 用end - start经saturating_sub可为 0两者都未指定 → 用整个剩余长度arg.len()即一直截到字符串末尾。边界值行为速查均有测试用例佐证见 tests/checks/string.fish#L216-L256string sub -l 6 abcde→abcde请求长度超过字符串本身时截断到末尾不报错。string sub -s 6 abcde→ 空行起始位置超出范围被 clamp 到末尾。string sub -s -100 abcde→abcde负起始值超出范围时 clamp 回 0。string sub -s -50 -e -100 abcde→ 空行结束位置比起始位置还靠前得到空串。string sub -s 2 -e -5 abcde→ 空行区间为空。string sub --start -9223372036854775808 abc→abci64 最小值也能安全处理见 tests/checks/string.fish#L83-L84。四、官方示例逐条验证官方文档 给出了 7 组示例这里逐条给出结果并注明其索引换算逻辑_ string sub --length 2 abcde ab只取前 2 个字符等价于 Python 的s[:2]。_ string sub -s 2 -l 2 abcde bc从第 2 个字符开始取 2 个字符start2 换算为 0-based 位置 1即b。_ string sub --start-2 abcde de负 start 从尾部数-2定位到d无 end/length 时一直取到末尾得到de。_ string sub --end3 abcde abc只给出 end3默认 start1取第 13 个字符。_ string sub -e -1 abcde abcdend-1 从尾部数即到倒数第 1 个字符为止等价于去掉最后一个字符。_ string sub -s 2 -e -1 abcde bcdstart2、end-1从b到倒数第 1 个字符之前得到bcd。_ string sub -s -3 -e -2 abcde cstart-3 定位到cend-2 定位到d含区间恰为单个字符c。再补几组来自测试文件的额外示例以便加深印象string sub --end-4 abcde→aend-4 换算为位置 1取第 1 个字符string sub -s -5 -e -2 abcdefgh→defstart-5 定位开头end-2 去掉末 2 个字符string sub -l 0 abcde→ 输出一个空行长度为 0 是合法的string sub -s -1 abcde→e负 start 只取最后一个字符五、退出状态与--quiet静默模式string sub的退出状态语义分三档这也是文档明确规定的行为退出状态含义触发条件0成功至少执行了一次子串截取操作nsub 01一般错误没有任何输入参数/没有任何截取操作被执行nsub 02参数错误选项组合非法、数值无法解析、--end与--length并用等其中无输入场景的典型例子_ string sub # 无 STRING 参数 # 退出状态为 1对应的源码判断在 src/builtins/string/sub.rs#L115-L119其单元测试plain也断言了validate!([string, sub], STATUS_CMD_ERROR, )。--quiet-q模式下命令不向 stdout 输出任何内容只返回退出状态且处理完第一个参数后立即提前返回不再读取后续输入这一提前退出行为同样适用于string家族其它子命令见 string 总览文档 对-q的说明。测试佐证_ string sub -q abcde # 无输出退出状态为 0典型用法是在条件判断中直接作为探针if string sub -q -s 2 -l 1 -- $value echo 该字符串至少有 2 个字符 end六、从标准输入读取与--分隔符string sub的输入来源遵循string家族的统一规则见 string 总览文档优先使用命令行参数作为 STRING若标准输入被连接到管道或文件则从 stdin 逐行读取每行作为一个 STRING命令行参数与 stdin 混用属于错误会以状态码 2 报错run_impl中的TOO_MANY_ARGUMENTS检查见 src/builtins/string.rs。因此string sub可以自然地接入管道echo hello, world | string sub -s 1 -l 5 # hellols | string sub -s 4 # 去掉每行前 3 个字符另外所有以-开头的参数默认被当作选项解析若要处理本身就是-开头的字符串需在其前加--分隔符例如string sub -l 2 -- -abc # -a这在补全脚本中非常常见例如 git.fish 补全 中对可能以-开头的行统一使用string sub -l 2 -- $line的写法。七、实战解析对齐文本与裁剪前后缀string sub在 fish 自带补全中承担了大量按列切片与去前缀工作以下是几处可复用的真实模式。按列宽度循环切片iwctl 补全share/completions/iwctl.fish 在解析iwctl表格输出时先量出各列宽度再用--length与动态--start逐列切分for line in (string match * -- $results[5..] | string sub -s (math $leading_ws 1)) for column_width in $column_widths printf %s\t (string sub -l $column_width -- $line | string trim -r) set line (string sub -s (math $column_width 1) -- $line) end printf \n end这里--start与--length均由math计算得出展示了两者组合切片 前进的分列处理思路。去掉固定前缀git / hg / npm 补全git.fish 补全 用string sub -l 2 -- $line提取状态行前 2 个字符做分支判断用string sub -s 4 -- $line去掉 4 字符前缀hg.fish 补全 用string sub -s 4 $line剥离输出前缀后再string split : -m 1取字段npm.fish 补全 用string sub -l $trim -- $value截取指定宽度的包名。取首字符大写化virsh 补全share/completions/virsh.fish 把-s1 -l1第一个字符与string upper组合实现首字母大写set -l desc (test -n $state; and echo (string sub -s1 -l1 -- $state | string upper)(string sub -s2 -- $state) domain; or echo Domain)其原理正是-s1 -l1取首字符 →string upper大写 → 再拼接-s2取出的剩余部分。八、与string家族其他子命令的组合string sub常与下列子命令协同使用均为string家族见 string 总览文档string trim先裁剪再切片或切片后string trim -r去除列尾空白iwctl 补全即此用法string upper/string lower对切片结果做大小写转换如 virsh 的首字母大写string split切片后按分隔符再拆分字段如 hg 补全string match先用匹配过滤行再对命中的行切片string length配合--length做动态定长截断如按列宽截取。string命令家族支持链式管道例如tests/checks/complete.fish中的string sub -l 1 -- $USER | string upper就是取环境变量首字符并大写的惯用写法。九、小结核心语法string sub [-s START] [-e END] [-l LENGTH] [-q] [STRING ...]1-based 索引正数从头部数、负数从尾部数默认 start1未给 end/length 时取到末尾。硬性约束--end与--length互斥start/end 不能为 0length 不能为负。边界安全所有越界索引都会通过saturating_sub与clamp收敛到合法范围超长长度截断到末尾绝不会产生越界访问。退出状态0 至少完成一次截取1 无操作执行2 参数/选项错误-q可静默探测。输入方式命令行参数或 stdin 逐行两者不可混用--用于转义以-开头的字符串。如果想继续深入推荐直接阅读以下仓库文件官方文档doc_src/cmds/string-sub.rst本文骨架来源Rust 实现src/builtins/string/sub.rs含索引换算与单元测试命令分发src/builtins/string.rsstring内建入口集成测试tests/checks/string.fish#L216-L256全部边界用例真实用法share/completions/iwctl.fish、share/completions/git.fish、share/completions/hg.fish、share/completions/virsh.fish赞分享CLI开发工具【免费下载链接】fish-shellThe user-friendly command line shell.项目地址https://gitcode.com/GitHub_Trending/fi/fish-shell点击查看免费下载相关推荐fish-shell contains 命令完全指南列表成员检测、索引输出与 -- 边界处理fish shell contains 命令完全指南列表成员检测、索引输出与 边界处理 contains 是 fish shell 内置的命令行工具用于判断CLI开发工具fish 内建 string 命令完全指南16 个子命令、PCRE2 正则与管道实战fish 内建 string 命令完全指南16 个子命令、PCRE2 正则与管道实战 string 是 fish shell 内置builtin的字符串处CLI开发工具fish shell 的 string upper 子命令字符串转大写与大小写检测实战指南fish shell 的 string upper 子命令字符串转大写与大小写检测实战指南 string upper 是 fish shell 内置 striCLI开发工具上一篇3 步跑起 GTA 三部曲SilentPatch 修复多显示器崩溃与高刷新率闪屏下一篇anarlog 听写Dictation插件权限参考完整权限标识、默认权限集与 Tauri ACL 实现解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表