prefer-jbang-automation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Prefer JBang for Automation

自动化优先选择JBang

Overview

概述

Prefer jbang scripts over bash commands for automation tasks.
While bash+jq/curl/awk work, jbang provides type safety, better debugging, IDE support, and maintainability. The slight overhead is worth it.
自动化任务优先选择jbang脚本而非bash命令。
虽然bash+jq/curl/awk也能实现需求,但jbang提供了类型安全、更优的调试能力、IDE支持以及可维护性,这点额外的开销是值得的。

Red Flags - STOP and Use JBang Instead

危险信号 - 立刻停止并改用JBang

If you're thinking any of these, STOP and write a jbang script instead:
  • "I'll use
    jq
    to parse this JSON"
  • "A quick
    curl | jq
    pipeline will work"
  • "Let me use
    sed
    or
    awk
    to transform this"
  • "Bash loop with grep/sed will handle this"
  • "This is a simple one-liner"
  • "jq is purpose-built for JSON"
All of these mean: Write a jbang script instead.
如果你有以下任何一种想法,立刻停下来,改为编写jbang脚本:
  • "我要用
    jq
    来解析这个JSON"
  • "一个简单的
    curl | jq
    管道就能搞定"
  • "我用
    sed
    或者
    awk
    来转换这个内容"
  • "带grep/sed的Bash循环就能处理"
  • "这就是个简单的单行命令"
  • "jq就是专门为JSON打造的"
以上所有情况都意味着:你应该编写jbang脚本。

When to Use JBang vs Bash

JBang与Bash使用场景对比

dot
digraph tool_choice {
    "Automation task?" [shape=diamond];
    "Simple file/git operation?" [shape=diamond];
    "Use Bash" [shape=box];
    "Use JBang" [shape=box];

    "Automation task?" -> "Simple file/git operation?" [label="yes"];
    "Automation task?" -> "Use Bash" [label="no"];
    "Simple file/git operation?" -> "Use Bash" [label="yes"];
    "Simple file/git operation?" -> "Use JBang" [label="no"];
}
Use JBang for:
  • JSON/XML parsing and transformation
  • REST API calls and processing
  • Data extraction and formatting
  • Multi-step file processing
  • Anything requiring logic beyond simple filters
  • Scripts you might need to debug or extend
Still use Bash for:
  • Git commands (
    git status
    ,
    git commit
    )
  • Simple file operations (
    ls
    ,
    cp
    ,
    mv
    )
  • System tools (
    chmod
    ,
    mkdir
    )
  • One-off glue commands
dot
digraph tool_choice {
    "Automation task?" [shape=diamond];
    "Simple file/git operation?" [shape=diamond];
    "Use Bash" [shape=box];
    "Use JBang" [shape=box];

    "Automation task?" -> "Simple file/git operation?" [label="yes"];
    "Automation task?" -> "Use Bash" [label="no"];
    "Simple file/git operation?" -> "Use Bash" [label="yes"];
    "Simple file/git operation?" -> "Use JBang" [label="no"];
}
JBang适用场景:
  • JSON/XML解析与转换
  • REST API调用与处理
  • 数据提取与格式化
  • 多步骤文件处理
  • 任何需要超出简单过滤器逻辑的场景
  • 你可能需要调试或扩展的脚本
仍适合使用Bash的场景:
  • Git命令(
    git status
    ,
    git commit
  • 简单文件操作(
    ls
    ,
    cp
    ,
    mv
  • 系统工具调用(
    chmod
    ,
    mkdir
  • 一次性粘合命令

Quick Reference

快速参考

Task❌ Avoid✅ Prefer
Parse JSON API
curl | jq
jbang script.java
with Jackson/Gson
Extract from JSON file
jq '.users[] | select'
JBang with type-safe POJOs
Transform data
sed | awk
pipeline
JBang with clear logic
Multiple file processingBash loopsJBang with Java NIO
任务❌ 不推荐✅ 推荐
解析JSON API
curl | jq
搭配Jackson/Gson的
jbang script.java
从JSON文件提取内容
jq '.users[] | select'
支持类型安全POJO的JBang
数据转换
sed | awk
管道
逻辑清晰的JBang
多文件处理Bash循环使用Java NIO的JBang

JBang Examples

JBang示例

JSON Processing

JSON处理

java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.google.code.gson:gson:2.10.1

import com.google.gson.*;
import java.nio.file.*;

public class ExtractEmails {
    record User(String name, String email, int age) {}
    record UserData(User[] users) {}

    public static void main(String[] args) throws Exception {
        var json = Files.readString(Path.of(args[0]));
        var data = new Gson().fromJson(json, UserData.class);

        for (var user : data.users) {
            if (user.age > 30) {
                System.out.println(user.email);
            }
        }
    }
}
Run:
jbang ExtractEmails.java users.json > emails.txt
Benefits over jq:
  • Type safety (compile errors if structure changes)
  • IDE autocomplete and debugging
  • Clear variable names and logic
  • Easy to extend (add validation, error handling)
java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.google.code.gson:gson:2.10.1

import com.google.gson.*;
import java.nio.file.*;

public class ExtractEmails {
    record User(String name, String email, int age) {}
    record UserData(User[] users) {}

    public static void main(String[] args) throws Exception {
        var json = Files.readString(Path.of(args[0]));
        var data = new Gson().fromJson(json, UserData.class);

        for (var user : data.users) {
            if (user.age > 30) {
                System.out.println(user.email);
            }
        }
    }
}
运行命令:
jbang ExtractEmails.java users.json > emails.txt
相比jq的优势:
  • 类型安全(如果结构变化会触发编译错误)
  • IDE自动补全与调试支持
  • 清晰的变量名与逻辑
  • 易于扩展(可添加校验、错误处理)

API Calls

API调用

java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.google.code.gson:gson:2.10.1

import com.google.gson.*;
import java.net.http.*;
import java.net.URI;
import java.time.*;
import java.time.format.*;

public class GithubRelease {
    record Release(String tag_name, String published_at) {}

    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.github.com/repos/jbangdev/jbang/releases/latest"))
            .build();

        var response = client.send(request, HttpResponse.BodyHandlers.ofString());
        var release = new Gson().fromJson(response.body(), Release.class);

        var published = Instant.parse(release.published_at);
        var formatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy 'at' HH:mm 'UTC'");

        System.out.println("Latest jbang Release Report");
        System.out.println("----------------------------");
        System.out.println("Tag: " + release.tag_name);
        System.out.println("Published: " + formatter.format(published.atZone(ZoneOffset.UTC)));
    }
}
Run:
jbang GithubRelease.java
Benefits over curl+jq:
  • Built-in HTTP client (no curl dependency)
  • Type-safe date handling
  • Readable formatting logic
  • Easy to add headers, auth, error handling
java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.google.code.gson:gson:2.10.1

import com.google.gson.*;
import java.net.http.*;
import java.net.URI;
import java.time.*;
import java.time.format.*;

public class GithubRelease {
    record Release(String tag_name, String published_at) {}

    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.github.com/repos/jbangdev/jbang/releases/latest"))
            .build();

        var response = client.send(request, HttpResponse.BodyHandlers.ofString());
        var release = new Gson().fromJson(response.body(), Release.class);

        var published = Instant.parse(release.published_at);
        var formatter = DateTimeFormatter.ofPattern("MMMM dd, yyyy 'at' HH:mm 'UTC'");

        System.out.println("Latest jbang Release Report");
        System.out.println("----------------------------");
        System.out.println("Tag: " + release.tag_name);
        System.out.println("Published: " + formatter.format(published.atZone(ZoneOffset.UTC)));
    }
}
运行命令:
jbang GithubRelease.java
相比curl+jq的优势:
  • 内置HTTP客户端(无curl依赖)
  • 类型安全的日期处理
  • 可读性强的格式化逻辑
  • 易于添加请求头、鉴权、错误处理

Common Rationalizations

常见辩解

ExcuseReality
"jq is purpose-built for JSON"JBang with Gson/Jackson is MORE purpose-built - type-safe, debuggable
"Single command is simpler"JBang scripts are just as easy:
jbang script.java args
"jq/curl are standard tools"JBang is standard for Java devs, more maintainable long-term
"Bash is more efficient"Slight overhead is worth type safety and debugging
"This is just a quick script"Quick scripts become production code - start with quality
"I don't need type safety"You discover you need it when the API changes
"I can solve this directly with jq"You're trading short-term convenience for long-term pain
"jq is efficient for single operations"JBang is efficient AND maintainable
"WebFetch + jq is simple"JBang HttpClient is simpler and type-safe
"Minimizes tool calls"JBang minimizes debugging time and maintenance burden
借口实际情况
"jq是专门为JSON打造的"搭配Gson/Jackson的JBang针对性更强 - 类型安全、可调试
"单条命令更简单"JBang脚本同样简单:
jbang script.java args
"jq/curl是标准工具"对于Java开发者来说JBang是标准工具,长期可维护性更强
"Bash效率更高"类型安全和调试能力带来的价值远高于微小的效率开销
"这只是个快速编写的脚本"快速脚本最终会演变为生产代码 - 从一开始就保证质量
"我不需要类型安全"当API结构变化时你就会发现你需要它
"我可以直接用jq解决这个问题"你是在用短期便利换取长期麻烦
"jq对单操作来说效率很高"JBang兼顾效率和可维护性
"WebFetch + jq很简单"JBang HttpClient更简单且支持类型安全
"可以减少工具调用"JBang减少了调试时间和维护负担

Pattern: Creating JBang Scripts

模式:创建JBang脚本

  1. Create file with
    .java
    extension
  2. Add shebang:
    ///usr/bin/env jbang "$0" "$@" ; exit $?
  3. Add deps:
    //DEPS group:artifact:version
  4. Write code: Regular Java with
    main()
    method
  5. Run:
    jbang ScriptName.java args
No compilation step needed - jbang handles it transparently.
  1. 创建扩展名为
    .java
    的文件
  2. 添加shebang
    ///usr/bin/env jbang "$0" "$@" ; exit $?
  3. 添加依赖
    //DEPS group:artifact:version
  4. 编写代码:带
    main()
    方法的常规Java代码
  5. 运行
    jbang ScriptName.java args
无需编译步骤 - jbang会透明处理编译过程。

When Bash is Still Right

仍适合使用Bash的场景

Don't overdo it. These stay in Bash:
  • git status && git diff
  • mkdir -p dir && cd dir
  • chmod +x script.sh
  • Calling system tools:
    gh pr create
    ,
    docker run
If the task is invoking a tool, use Bash. If the task is processing data or logic, use JBang.
不要过度使用JBang,以下场景仍使用Bash:
  • git status && git diff
  • mkdir -p dir && cd dir
  • chmod +x script.sh
  • 调用系统工具:
    gh pr create
    ,
    docker run
如果任务是调用工具,使用Bash。 如果任务是处理数据或逻辑,使用JBang。