分类目录归档:不是技术

sed

kimi还有一个破毛病,喜欢用sed来编辑脚本。

出了几次反复修改改错代码的问题。我终于忍不住问DeepSeek为什么。

这是一个很敏锐的观察。AI(比如我)在生成 `sed` 命令时确实容易出错,主要原因可以归结为以下几点:

### 1. 分隔符冲突
`sed` 默认使用 `/` 作为分隔符,但 AI 常常忽略目标字符串中也包含 `/` 的情况。

-   **错误例子**:你想把路径 `/bin/bash` 改成 `/usr/bin/zsh`。AI 直接生成 `sed ‘s//bin/bash//usr/bin/zsh/’` —— 这会导致语法错误,因为 `/` 提前结束了模式。
-   **正确做法**:需要转义 `/`(`\/`),或者改用其他分隔符,比如 `#` 或 `|`:`sed ‘s#/bin/bash#/usr/bin/zsh#’`。AI 常常忘记处理这种冲突。

### 2. 特殊字符未转义
`sed` 中的很多字符有特殊含义:`.`、`*`、`[`、`]`、`^`、`$`、`\`、`&` 等。

-   **错误例子**:你想替换 `IP地址:192.168.0.1` 中的 IP。AI 可能会写 `sed ‘s/192.168.0.1/new_ip/’` —— 但这里的 `.` 会匹配**任意字符**,而不是字面上的点。
-   **后果**:它可能匹配到 `192X168Y0Z1` 这样的奇怪组合,或者替换失败。AI 自动生成时往往忽略对这些元字符的转义(应该写成 `192\.168\.0\.1`)。

### 3. 分组和反向引用的跨平台差异
在 `sed` 中,使用 `()` 进行分组时:

-   **GNU sed(Linux)**:需要用 `\(` 和 `\)` 来转义,反向引用是 `\1`。
-   **BSD sed(macOS、FreeBSD)**:基本 POSIX 模式下,`(` 和 `)` 也必须转义才能作为分组符,不过 `\1` 用法类似。
-   **更混乱的**:有些脚本想用 `-E` 选项(扩展正则)来避免转义,但 AI 生成的命令常常**混用**两种风格,或者不加 `-E` 却用了无需转义的正则写法,导致报错或静默失败。

例如:想交换两个单词 `Hello World` → `World Hello`。正确的 GNU 写法是 `sed ‘s/\(Hello\) \(World\)/\2 \1/’`。如果 AI 忘记转义括号,写成 `sed ‘s/(Hello) (World)/\2 \1/’`,则完全无效。

### 4. `-i` 选项的平台差异
`sed -i`(原地修改文件)的行为在 Linux 和 macOS 上不同:

-   **Linux**:`sed -i ‘s/old/new/’ file`
-   **macOS**:`sed -i ‘’ ‘s/old/new/’ file` —— 必须为备份后缀提供一个空字符串参数,否则会报错。

AI 经常默认用 Linux 语法,导致在 macOS 上运行时出现奇怪的 `sed: -i may not be used with stdin` 或 `undefined label` 错误。

### 5. 边界条件与文件格式
-   **缺少换行符**:如果文件最后一行没有换行符,某些 `sed` 命令(如 `$` 地址匹配)可能表现异常。
-   **Windows 换行符(CRLF)**:`sed` 默认把 `\r` 当作普通字符,导致模式匹配失败(比如你搜 `foo$` 匹配不到 `foo\r\n`)。
-   **空文件**:一些 `sed` 脚本在空文件上会直接报错退出。

AI 在生成命令时,默认假设一个整洁的 POSIX 文本文件,但现实中并不总是如此。

### 6. AI 的“统计学习”问题
大模型的训练数据里包含大量 **错误的、过时的、不兼容的** `sed` 示例。比如:

-   来自 Stack Overflow 上某个未被采纳的答案。
-   来自个人博客里随意测试的片段。
-   来自混合了不同 shell 环境的历史脚本。

模型学会了“最常见”的写法,而不是“在所有情况下都正确”的写法。对于小众边缘情况(如处理路径、JSON、XML),模型更容易编造一个看起来合理但实际错误的命令。

### 7. 对上下文理解不足
用户往往只说“帮我改一下这个配置文件里的 IP”,但不提供文件的具体格式、是否有特殊符号、使用的是哪种 `sed` 版本。AI 只能盲目猜测,而猜测的结果就是容易出错。

### 如何减少错误?
-   **先测试**:运行 `sed` 前,先用 `sed ‘s/pattern/replacement/’ file`(不加 `-i`)看看输出是否正确。
-   **告诉 AI 更多信息**:明确说明“我的文件路径包含斜杠”“我用的是 macOS”“IP 地址里有小数点”。
-   **换工具**:对于结构化的文本(JSON、YAML、XML、CSV),用专门的解析器(`jq`、`yq`、`xq`、`awk`)而不是 `sed`。AI 生成的 `awk` 或 `perl` 命令有时比 `sed` 更可靠,因为语法更一致。
-   **加上 `--debug`**:如果 `sed` 版本支持(如 GNU sed 4.8+),用 `sed --debug` 看它是如何解释命令的。

总的来说,不是 AI 能力不足,而是 `sed` 本身是一个非常“挑剔”、充满历史包袱和平台差异的工具。AI 擅长的是统计规律,而不是绝对正确的语法和边界条件。对于关键的文件操作,**永远不要盲目信任 AI 生成的 `sed` 命令**。

明白了,于是让Kimi把不用sed写到AGENTS.md里。

自以为是的CLI

在调试过程中,我让kimi帮我checkout回git的最新版本。

然后发现它给我git clean了,于是一大堆untracked的目录被干掉了。骂了它十几句。

得到的结果就是我以为,对不起,有没有Time Machine,很废。

于是我告诉它不要用git了,除非我命令它用。

好在前两天都及时git commit过了,损失不算大,就是10美元额度能追回的事情。

有点心理阴影,还是让codex去恢复/重做这些untracked的事情了。

把额度花光

连续几天都把codex两个来源的每日额度都花光了。

我的性格是每天有非常确切的事情做,细到一定地步会非常的充实,也很有存在感。

这种花额度干活的方式,让整个白天工作时间都很饱和……比以前技术管理/公司管理的时候更实在。然后不断地为额度为tokens想着办法花完它。

不过坏处也是有的,欠的阅读清单一直都没有完成。

codex 5.4用了一个月了,然后5.5也来了,不过要pro套餐才行,我在考虑,一个什么样的任务再启动5.5的工作。毕竟目前的任务,都分配好了(kimi:前端系统, codex:三维算法及场景分析),也比较顺利,如无必要,勿增实体,总不好无事换帅吧。

判断何时用算法,何时用人工

在某个细分领域上,你要提升一点点,能参考的东西也不多,好在现在AI的能力很强,但AI会把人带偏,它们会习惯性地用科研的思维去尝试解决问题,这样的做法在工程上有时候是相当不合适的。

比如,做出一个有效算法,样本集和测试集是否足够,算法的复杂度是否足够高,以至于产品化的时候很鸡肋。

相比之下,如果我们在输入端,要求输入的格式就按需求做了某些调整,这样就很大地减少了算法的复杂度。

但谁来做这个决定,肯定是vibe coder了。这就要求viber coder,既懂科研标准,也知道工程限制,更重要的是,知道需求的本质是什么,需求方是否可以妥协。

开了ChatGPT Plus

略复杂:

挖出不用两年的顶配iPhone 11,系统升到最新,注册了新的美区 Apple Account

Gift Card陆续充值,养了一个月,购买一些低价游戏玩了一下

(美区Apple Account不支持中国的信用卡绑定Apple Pay,但可以用美区Gift Card充值,美区Gift Card商店支持中国的支付方式:支付宝等)

下载了ChatGPT,玩了一段free的对话

注册了新的Gmail账号

ChatGPT切换到新的Gmail账号

(新的Gmail账号如果被封,iOS上的ChatGPT更换账号就可以了,但如果Apple Account被封可能就比较麻烦?)

新账号升级到Plus

删掉之前中转站用的auth.json和config.toml

(之前的中转站是API体系,base_url和API_KEY写在那里,触发不了ChatGPT账号登录,ChatGPT账号也可以建立API KEY,但使用API KEY是额外收费的,不在套餐里)

重启codex,用ChatGPT登录。

感觉费用消耗上会比中转站可靠还便宜,对于我的使用度来说(每天100M tokens左右)

(Plus计划没有用量统计,只有用了五小时限额/周限额多少的百分比,如果要看具体的就要部署sub2api的系统了)

先不把话说满,谁知道后面会如何。

Codex 中转站的价格

由于之前的中转站老出问题,月卡差不多算是废了,尽管它的消耗比率目前看来比其他要合理很多。

转向买日卡或者按量充值。

换算公式甚是啰嗦:你消耗的M token数 — 折算成系统的token计价单位:“美元”(理解成赌场上的筹码也可以) — 为了提升服务质量,用什么样的比率消耗这些“美元” — 商家用什么样的汇率来销售这些美元 — 你买的codex服务使用的人民币

作为CLI用户,更关心的是使用的 M tokens 和最终的 RMB的比例。

过程中的赚钱的地方:

  1. tokens的消耗速度,试过有个站用得特别特别快,就是算tokens算多了,就欺负你不去计较它。
  2. 消耗“美元”的比率,最初用的站比较良心,还是1:1的,后来不怎么能用了,到外面看一圈,很多把比率调成2倍或以上。我这两天用的就是2倍的。系统中用1“美元”,计价2“美元”。
  3. 人民币购买“美元”的汇率,有些老牌的商业站,用1:1来销售,但从2.的比率上设成0.2~0.5,也有些新站,汇率是1:30(1 RMB购买30美元),但2.比率就是几倍。

所以2 和 3要乘起来一起看。

还会有更猫腻的地方,如果你用来玩龙虾的话,由于你基本上看不到过程,有可能换其他模型来以次充好。

号池:

中转站的生意其实是黑产/灰产的下游,正正经经自己买号建号池再来分销,(其实也是不符合原厂的用户协议),要赚钱无非是上面几个点位。

很多是从号商处购买各种原厂大模型的商用号。

这些号是怎么来的,一方面是自动注册,另一方面是钻AI原厂的支付漏洞,成本会低得离谱。就是多了一个被封号的风险,所以卖号的会承担部分封号的风险:退款或者换号等。

带来同样的机会就是代充服务……

由于AI中转站是一个非常新兴的特殊的行业,目前看不到后面会怎么发展。如果不看重盈利的话,几个个人 / 团队正规途径合买一些商业号,建中转系统共用,会是一个可靠的模式。(跟当年几个人共用梯子很像吧)

大模型厂商比如OpenAI会怎么看这些问题?估计就是:让子弹飞一会儿吧。

与kimi cli的开发反思

更多的是我在反思,让kimi看看它跟我的理念的差异,造成了一些不顺畅以及技术债务。

节选一下:

## 对 AI 的提示

在后续开发中,当遇到以下信号时,应主动质疑而不是默认实现:

1. 某个功能不在 `ROADMAP.md`、设计文档或用户明确指令中

2. 功能的加入理由是 “xxx 软件也有”

3. 修复一个边缘 bug 需要引入复杂的条件分支

4. 功能在复杂架构下语义不清

5. 正在解决的问题与之前已解决的问题高度相似

6. 同一个模块/功能反复出现相似 bug

此时应优先向用户确认:

> “这个功能不在当前设计范围内,且边界较复杂。建议是 A) 简化实现 B) 直接删除 C) 排期设计。您的偏好是?”

当遇到实现困难时,应优先执行以下检查清单:

1. **搜索当前代码库**:是否有同一模块中已解决的相似问题?

2. **搜索历史修改记录**:CHANGELOG / git history 中是否有相关修复?

3. **查看原始参考**:`xxxxxx/` 原始 C++ 代码中是否有对应逻辑?

4. **检查可复用组件**:是否有公共函数、工具类、或已有模式可以直接套用?

5. 只有在上述四步都没有找到答案时,才允许从零实现。

**注意**:第 1-4 步的参考价值**高于**第 5 步中你可能想到的”通用最佳实践”。参考代码包含了本项目的具体约束和验证过的边界条件。

当脑海中浮现”我知道一个更好的方案”时,应问自己:

1. 这个”更好的方案”是**当前项目真正需要的**,还是**我知识库中恰好有的**

2. 如果用一个简单方案实现 80% 的价值,**剩下 20% 是否值得引入额外的复杂度**

3. 这个方案如果被证明过度设计,**是否容易拆除**

4. 手头的参考代码(第三方源码或项目内已有实现)是否已经给出了**更适合当前约束的答案**

新的通道

因为EC2的速度实在是感人,而且免费期已经过了一半的时间,我估计还是要找偏移的更好的。

于是找了个新的,但考虑到LAX那边线路虽好,但IP都被中国人用得拥挤不堪,于是还是找了个佛州的节点。

现在的VPS服务真真自动化,下单的时候就让你选好OS和预装的VPN服务软件,可以用了,就直接邮件通知,省心省事。

改yaml,然后测速,发现延迟并没有比EC2(美东的节点)好多少,但丢包率很赞,0%……

先用着吧,我是最怕人多了。

贵计算

也许是我总是强调效率、优化、性能这些关键词,codex冷不丁给我来了一句:

才进贵计算 是什么意思?

我心想,这不是什么互联网/开发黑话吧,大概是从英文翻译过来,但英文原文如果是expensive computation也不见得有多流行。

gemini cli

1.系统proxy不认,还要export https_proxy

2.要授权项目使用gemini api

3.只看到有2.5 (pro / flash / …) ,3.0没有完全开放

4. Gemini 2.5很笨,在kimi和codex里面,它们都很轻松把要的资料下下来了,gemini动不动就说我找不到、找不到。哪怕给了它页面,它都区分不出哪一个zip包是要下载的。

5. Google的强大就剩下庞大的生态了,也能后来居上,但这种服务态度,怎么办啊。