← 返回日报
略读 预计 1 分钟

how a stray "j" ruined my evening

摘要

作者写了一个简单的链接短缩脚本(shell script + wl-clipboard),长期正常使用。后来在使用 Signal 的 TUI 客户端 gurk 分享 S3 图片链接时,收到反馈说链接 404,但自己本地打开却正常。进一步对比多条消息后发现所有失败链接末尾都多了一个字母 “j”。最终定位原因是复制链接时末尾带了换行符 \n,而在某些终端 / ANSI 处理链路中该控制字符被错误解释并转换成了字符 “j”,污染了 URL。解决方式是让 jq 使用 --join-output 避免输出末尾换行。文章主要围绕这个 “隐藏换行导致链接被篡改” 的调试过程展开。

荐读理由

使用 jq 的 --join-output 参数能避免 ANSI newline 转成 stray j 导致链接 404

原文

← back 2026-06-08

Some time ago I decided to wrangle a silly link shortener that I called shirts linkener, shirts for short.

There's nothing special about it in particular, rather it's in my run-once-forget-forever shell script that copies the generated links to a clipboard using wl-clipboard.

#!/bin/sh

shirt=$(curl -s -X POST "$(pass show shirts/url)" \
    -H "Authorization: Bearer $(pass show shirts)" \
    -H "Content-Type: application/json" \
    -d "{\"url\": \"${1?missing url}\"}")

echo "$shirt" | jq
echo "$shirt" | jq -r '.short_url' | wl-copy

Nothing out of the ordinary here. It shortens the link and copies it to a clipboard. By then I have been hapilly using it for couple of months without an issue.

The fun began when I decided to try out gurk, a Signal TUI written in Rust. Those who know me, know my obsession with terminal interfaces so this was an obvious match.

One evening I was sharing a link to an image hosted on S3 when I noticed people were saying it shows 404 to them.

After pasting the link into Firefox, it worked. What is going on? I send them the link and it works now...

Time passes and I get the same responses from multiple friends - 404. After some time looking at the messages I notice a pattern - each url ends with "j".

Turns out I was copying the link with a \n at the end, which in most cases went unnoticed, but in ANSI newline delimiter is translated as "j", hence the stray jay at the end of each link.

After having a solid five minutes of immense shame I found that jq has --join-output argument, which prevents exactly my case:

     --join-output / -j:

            Like -r but jq won't print a newline after each output.

Moral of this story is that terminals are fun and shooting myself in the foot repeatedly acts as a great learning opportunity.

Some of the sources around control codes and escape sequences.

m.

Lobsters · 2 赞 · 2 评 讨论 → 阅读原文 →

这条对你有帮助吗?