如何用awk printf实现表格列完美对齐的格式化输出?
实现带边框的整齐表格输出
问题背景
你尝试用以下awk命令处理以_,,,_为分隔符的数据,通过printf指定%-10s格式输出并配合column命令对齐:
awk 'BEGIN { FS = "_,,,_" printf "%-10s | %-10s | %-10s\n", "Date", "Tag", "Name" } ; { date=strftime("%Y-%m-%d %H:%M",$2) ; printf "%-10s | %-10s | %-10s\n", date, $1, $3 }' | column -t -s "|"
但因为列内容长度差异大,column无法实现完美对齐,当前输出为:
Date Tag Name 2020-11-11 06:12 foo foo 2020-11-11 06:12 bar something-with-a-longer-name 2020-11-11 06:12 something-with-a-longer-name bar
你希望得到带边框的整齐表格输出:
_____________________________________________________________________________________ | Date | Tag | Name | |-----------------------------------------------------------------------------------| | 2020-11-11 06:12 | foo | foo | | 2020-11-11 06:12 | bar | something-with-a-longer-name | | 2020-11-11 06:12 | something-with-a-longer-name | bar | -------------------------------------------------------------------------------------
解决方案
放弃column命令,直接用awk完成所有格式控制——先遍历所有数据统计每列的最大宽度,再根据这个宽度生成统一格式的表格,包括边框。修改后的命令如下:
awk 'BEGIN { FS = "_,,,_" # 定义表头 headers[1] = "Date" headers[2] = "Tag" headers[3] = "Name" # 初始化列宽为表头长度 col_width[1] = length(headers[1]) col_width[2] = length(headers[2]) col_width[3] = length(headers[3]) } # 第一遍遍历:统计每列最大宽度 { date = strftime("%Y-%m-%d %H:%M", $2) # 存储每行数据 row[NR][1] = date row[NR][2] = $1 row[NR][3] = $3 # 更新列宽 len = length(date) if (len > col_width[1]) col_width[1] = len len = length($1) if (len > col_width[2]) col_width[2] = len len = length($3) if (len > col_width[3]) col_width[3] = len } # 处理完所有行后输出表格 END { # 计算总宽度:各列宽+分隔符和边距的长度 total_width = col_width[1] + col_width[2] + col_width[3] + 8 # 3个" | " + 左右"| "和" |" # 输出顶部边框 printf "%s\n", sprintf("%" total_width "s", "") gsub(/ /, "_", $0) print $0 # 输出表头行 printf "| %-" col_width[1] "s | %-" col_width[2] "s | %-" col_width[3] "s |\n", headers[1], headers[2], headers[3] # 输出分隔线 printf "|%s|\n", sprintf("%" (total_width - 2) "s", "") gsub(/ /, "-", $0) print $0 # 输出数据行 for (i=1; i<=NR; i++) { printf "| %-" col_width[1] "s | %-" col_width[2] "s | %-" col_width[3] "s |\n", row[i][1], row[i][2], row[i][3] } # 输出底部边框 printf "%s\n", sprintf("%" total_width "s", "") gsub(/ /, "-", $0) print $0 }' your_data_file.txt
关键说明
- 统计列宽:先遍历所有行,记录每列内容的最大长度,确保长内容不会溢出或错位。
- 统一格式输出:用计算好的列宽配合
printf的%-Ns格式,保证每列左对齐且宽度一致。 - 边框生成:通过
sprintf生成指定长度的空格字符串,再替换成_或-作为边框线。
替换your_data_file.txt为你的实际数据文件名,直接运行即可得到符合预期的带边框整齐表格。
内容的提问来源于stack exchange,提问作者NodeJSNoob
相关产品推荐
相关产品推荐

