标准输出三件套是
println、@show,精确格式靠格式化包,交互输入用readline。这一节全在 REPL 里练,十分钟过完,但都是天天用的动作。
print("不换行") println("自动换行") x = 3.14159 @show x # 输出 x = 3.14159,调试神器 println("圆周率约等于 $x") # 插值 println("三位小数:$(round(x, digits=3))")
@show 值得单独记:它把"表达式原文 + 值"一起打出来,排查循环里变量状态时比反复写 println 省一半字符。
标准库 Printf 提供 C 风格的格式模板:
using Printf @printf("整数:%d\n", 42) @printf("定点:%.3f\n", π) # 3.142 @printf("科学计数:%.2e\n", 6.022e23) @printf("宽度对齐:%8.2f|\n", 12.345) # 占 8 字符右对齐 s = @sprintf("结果 = %.4f", 2.0^0.5) # 格式化成字符串而不是打印
| 模板 | 含义 | 示例输出 |
|---|---|---|
%d |
整数 | 42 |
%.3f |
定点三位小数 | 3.142 |
%.2e |
科学计数 | 6.02e+23 |
%8.2f |
宽度 8 右对齐 | 12.35 |
%s |
字符串 | abc |
println("你叫什么名字?") name = readline() # 读一行(去掉换行符) println("你好,$name!") n = parse(Int, readline()) # 读一行并转整数 println("明年你 $(n + 1) 岁")
⚠️ 常见坑:
readline拿到的一定是字符串,parse(Int, s)失败会抛异常。对不可信输入,用tryparse(Int, s),失败返回nothing,配合isnothing判断更稳。
REPL 里可以直接体验 shell 管道式的流:
run(pipeline(`echo hello`, `sort`)) # 外部命令接管道 eachline(stdin) # 逐行消费标准输入 for line in eachline("data.txt") println(length(line)) end
run 加反引号执行外部命令,pipeline 把多个命令串起来——写数据处理小工具时,这比切换到 shell 脚本更顺手。
背景:跑完一批仿真,要把参数与误差汇总成一张对齐的文本报表贴进论文附录或群聊。这类活儿考验的就是格式化功底。第一步,准备数据:
results = [ ("欧拉法", 100, 1.63e-2) ("改进欧拉", 100, 4.05e-3) ("RK4", 100, 6.35e-7) ]
第二步,用 @printf 控制列宽与小数位,让三列对齐:
using Printf @printf("%-12s%8s%14s\n", "方法", "步数", "误差") # -号表示左对齐 for (name, n, err) in results @printf("%-12s%8d%14.2e\n", name, n, err) end # RK4 100 6.35e-07
解读:中文名字宽度不定,给方法列留 12 字符并左对齐,数值列右对齐,一张表立刻有了"仪器输出"的质感。变式:把 @printf 换成 @sprintf 收集每行字符串,join 后写文件或发网络请求都行——报表逻辑与输出目标解耦,是这段代码真正的骨架。
println 默认打到标准输出,但 Julia 的打印函数第一个参数都可以是任意 IO 流。这意味着同一个函数既能打屏幕也能写文件:
function report(io::IO, title) println(io, "== $title ==") println(io, now()) end report(stdout, "屏幕版") # 打到控制台 open("report.txt", "w") do io report(io, "文件版") # 写进文件,函数零改动 end
给每个输出函数都留一个 io::IO 首参数,是 Julia 标准库的一致风格,照着写,自己的代码自动获得可测试性——测试时传个 IOBuffer() 就能截获输出做断言,不必真的落盘。这个习惯成本极低,越早养成收益越大。
三个不显眼但咬人的细节。一是中文输出到 Windows 老控制台可能显示乱码,根源是控制台代码页而非 Julia;在代码页 65001(UTF-8)的终端里一切正常,脚本输出到文件再查看则从不受此影响。二是缓冲:print 到文件流默认带缓冲,程序中途被杀掉时最后一段输出可能没落盘,对日志要求高的场景用 flush(io) 主动冲刷,或在 open 后对关键节点即时 flush。三是错误流分离:警告与报错应打到 stderr 而不是 stdout,Julia 里 @warn、@error 宏自动走 stderr,管道重定向时正常输出与诊断信息就不会互相污染——写给别人当命令行工具用的脚本,这条是专业度的分水岭:
@info "开始处理" n = length(rows) # 结构化日志,自动进 stderr @warn "跳过坏行" line = 42 @error "致命错误,退出"
结构化日志宏的好处是键值对形式,后续用工具按字段过滤日志时无需正则解析文本。
@show 是调试打印的第一选择;@printf / @sprintf 处理对齐与小数位,模板记 %d %.3f %8.2f 三件;readline + parse 组合读输入,不可信输入换 tryparse;pipeline 在 Julia 里直接编排外部命令。