首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

一个能够生成 Markdown 表格的 Bash 脚本

编程知识
2024年08月22日 08:53

哈喽大家好,我是咸鱼。

今天分享一个很实用的 bash 脚本,可以通过手动提供单元格内容和列数或者将带有分隔符的文件(如 CSV、TSV 文件)转换为 Markdown 表格。

源代码在文末哦!原文链接:https://josh.fail/2022/pure-bash-markdown-table-generator/

具体功能:

  • 手动生成表格:允许用户输入表格内容和列数,生成标准的 Markdown 格式表格。
  • 文件转换:可以将 CSV 或 TSV 文件转换为 Markdown 表格。
  • 选项支持:支持指定列数、设置分隔符、解析 CSV/TSV 文件等选项。

主要选项:

  • -COLUMNS:设置生成表格的列数。
  • -sSEPARATOR:自定义输入文件的列分隔符。
  • --csv--tsv:分别用于解析 CSV 和 TSV 文件。

几个月前,我想要一个便携式的 Markdown 表格生成器,于是写了这个 markdown-table 脚本。

一开始我只是想传入一堆参数和列数,并让它生成相应的 Markdown 表格。就像下面的例子:

markdown-table -4 \
 "Heading 1"  "Heading 2" "Heading 3" "Heading 4" \
 "Hi"         "There"     "From"      "Markdown\!" \
 "Everything" "Is"        "So"        "Nicely Aligned\!"

当我实现了这一功能后,我意识到还可以添加支持解析带有自定义分隔符的文件,比如 CSV 或 TSV。

markdown-table --tsv < test.tsv

上面两种方法都会生成一个 Markdown 表格:

| Heading 1  | Heading 2 | Heading 3 | Heading 4      |
| ---------- | --------- | --------- | -------------- |
| Hi         | There     | From      | Markdown       |
| Everything | Is        | So        | Nicely Aligned |
#!/usr/bin/env bash
# Usage: markdown-table -COLUMNS [CELLS]
#        markdown-table -sSEPARATOR < file
#
# NAME
#   markdown-table -- generate markdown tables
#
# SYNOPSIS
#   markdown-table -COLUMNS [CELLS]
#   markdown-table -sSEPARATOR < file
#
# DESCRIPTION
#   markdown-table helps generate markdown tables. Manually supply arguments
#   and a column count to generate a table, or pass in a delimited file to
#   convert to a table.
#
# OPTIONS
#   -COLUMNS
#       Number of columns to include in output.
#
#   -sSEPARATOR
#       String used to separate columns in input files.
#
#   --csv
#       Shortcut for `-s,` to parse CSV files. Note that this is a "dumb" CSV
#       parser -- it won't work if your cells contain commas!
#
#   --tsv
#       Shortcut for `-s$'\t'` to parse TSV files.
#
#   -h, --help
#       Prints help text and exits.
#
# EXAMPLES
#   Build a 4 column markdown table from arguments:
#     markdown-table -4 \
#       "Heading 1"  "Heading 2" "Heading 3" "Heading 4" \
#       "Hi"         "There"     "From"      "Markdown!" \
#       "Everything" "Is"        "So"        "Nicely Aligned!"
#
#   Convert a CSV file into a markdown table:
#     markdown-table -s, < some.csv
#     markdown-table --csv < some.csv
#
#   Convert a TSV file into a markdown table:
#     markdown-table -s$'\t' < test.tsv
#     markdown-table --tsv < test.tsv

# Call this script with DEBUG=1 to add some debugging output
if [[ "$DEBUG" ]]; then
  export PS4='+ [${BASH_SOURCE##*/}:${LINENO}] '
  set -x
fi

set -e

# Echoes given args to STDERR
#
# $@ - args to pass to echo
warn() {
  echo "$@" >&2
}

# Print the help text for this program
#
# $1 - flag used to ask for help ("-h" or "--help")
print_help() {
  sed -ne '/^#/!q;s/^#$/# /;/^# /s/^# //p' < "$0" |
    awk -v f="$1" '
      f == "-h" && ($1 == "Usage:" || u) {
        u=1
        if ($0 == "") {
          exit
        } else {
          print
        }
      }
      f != "-h"
      '
}

# Returns the highest number in the given arguments
#
# $@ - one or more numeric arguments
max() {
  local max=0 arg

  for arg; do
    (( ${arg:-0} > max )) && max="$arg"
  done

  printf "%s" "$max"
}

# Formats a table in markdown format
#
# $1 - field separator string
format_table() {
  local fs="$1" buffer col current_col=0 current_row=0 min=3
  local -a lengths=()

  buffer="$(cat)"

  # First pass to get column lengths
  while read -r line; do
    current_col=0

    while read -r col; do
      lengths["$current_col"]="$(max "${#col}" "${lengths[$current_col]}")"

      current_col=$((current_col + 1))
    done <<< "${line//$fs/$'\n'}"
  done <<< "$buffer"

  # Second pass writes each row
  while read -r line; do
    current_col=0
    current_row=$((current_row + 1))

    while read -r col; do
      printf "| %-$(max "${lengths[$current_col]}" "$min")s " "$col"

      current_col=$((current_col + 1))
    done <<< "${line//$fs/$'\n'}"

    printf "|\n"

    # If this is the first row, print the header dashes
    if [[ "$current_row" -eq 1 ]]; then
      for (( current_col=0; current_col < ${#lengths[@]}; current_col++ )); do
        printf "| "
        printf "%$(max "${lengths[$current_col]}" "$min")s" | tr " " -
        printf " "
      done

      printf "|\n"
    fi
  done <<< "$buffer"
}

# Main program
main() {
  local arg cols i fs="##$$FS##"

  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h | --help) print_help "$1"; return 0 ;;
      -[0-9]*) cols="${1:1}"; shift ;;
      -s*) fs="${1:2}"; shift ;;
      --csv) fs=","; shift ;;
      --tsv) fs=$'\t'; shift ;;
      --) shift; break ;;
      -*) warn "Invalid option '$1'"; return 1 ;;
      *) break ;;
    esac
  done

  if [[ -z "$fs" ]]; then
    warn "Field separator can't be blank!"
    return 1
  elif [[ $# -gt 0 ]] && ! [[ "$cols" =~ ^[0-9]+$ ]]; then
    warn "Missing or Invalid column count!"
    return 1
  fi

  { if [[ $# -gt 0 ]]; then
      while [[ $# -gt 0 ]]; do
        for (( i=0; i < cols; i++ )); do
          if (( i + 1 == cols )); then
            printf "%s" "$1"
          else
            printf "%s%s" "$1" "$fs"
          fi
          shift
        done

        printf "\n"
      done
    else
      cat
    fi
  } | format_table "$fs"
}

main "$@"
From:https://www.cnblogs.com/edisonfish/p/18373149
本文地址: http://shuzixingkong.net/article/1318
0评论
提交 加载更多评论
其他文章 从源码分析 SpringBoot 的 LoggingSystem → 它是如何绑定日志组件的
开心一刻 今天心情不好,想约哥们喝点 我:心情不好,给你女朋友说一声,来我家,过来喝点 哥们:行!我给她说一声 我:你想吃啥?我点外卖 哥们:你俩定吧,我已经让她过去了 我:???我踏马让你过来!和她说一声 哥们:哈哈哈,我踏马寻思让她过去呢 前情回顾 SpringBoot2.7 霸王硬上弓 Log
从源码分析 SpringBoot 的 LoggingSystem → 它是如何绑定日志组件的 从源码分析 SpringBoot 的 LoggingSystem → 它是如何绑定日志组件的 从源码分析 SpringBoot 的 LoggingSystem → 它是如何绑定日志组件的
DDD建模后写代码的正确姿势(Java、dotnet双平台)
本文书接上回《一种很变态但有效的DDD建模沟通方式》,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新; DDD框架源码(.NET、Java双平台); 加群畅聊,建模分析、技术交流; 视频和直播在B站。 终于到了写代码的环节 如果你已经阅读过本系列前面的所有文章,我相信你对需求分析和建模设计有
DDD建模后写代码的正确姿势(Java、dotnet双平台) DDD建模后写代码的正确姿势(Java、dotnet双平台) DDD建模后写代码的正确姿势(Java、dotnet双平台)
使用分布式锁解决IM聊天数据重复插入的问题
导航 业务背景 问题分析与定位 探索可行的解决方案 数据库层面处理——唯一索引 应用程序层面处理——分布式锁 分布式锁概述 分布式锁需要具备哪些特性? 分布式锁有哪些实现方式? 基于数据库的实现方式 基于Redisson实现方式 Redission介绍 概述 可重入锁 基于Redisson解决方案
使用分布式锁解决IM聊天数据重复插入的问题 使用分布式锁解决IM聊天数据重复插入的问题 使用分布式锁解决IM聊天数据重复插入的问题
Dapr v1.14 版本已发布
Dapr是一套开源、可移植的事件驱动型运行时,允许开发人员轻松立足云端与边缘位置运行弹性、微服务、无状态以及有状态等应用程序类型。Dapr能够确保开发人员专注于编写业务逻辑,而不必分神于解决分布式系统难题,由此显著提高生产力并缩短开发时长。Dapr 是用于构建云原生应用程序的开发人员框架,可以更轻松
聊聊 PHP 多进程模式下的孤儿进程和僵尸进程
在 PHP 的编程实践中多进程通常都是在 cli 脚本的模式下使用,我依稀还记得在多年以前为了实现从数据库导出千万级别的数据,第一次在 PHP 脚本中采用了多进程编程。
聊聊 PHP 多进程模式下的孤儿进程和僵尸进程 聊聊 PHP 多进程模式下的孤儿进程和僵尸进程
零基础学习人工智能—Python—Pytorch学习(七)
前言 本文主要讲神经网络的下半部分。 其实就是结合之前学习的全部内容,进行一次神经网络的训练。 神经网络 下面是使用MNIST数据集进行的手写数字识别的神经网络训练和使用。 MNIST 数据集,是一个常用的手写数字识别数据集。MNIST 数据集包含 60,000 张 28x28 像素的灰度训练图像和
零基础学习人工智能—Python—Pytorch学习(七) 零基础学习人工智能—Python—Pytorch学习(七) 零基础学习人工智能—Python—Pytorch学习(七)
SLAB:华为开源,通过线性注意力和PRepBN提升Transformer效率 | ICML 2024
论文提出了包括渐进重参数化批归一化和简化线性注意力在内的新策略,以获取高效的Transformer架构。在训练过程中逐步将LayerNorm替换为重参数化批归一化,以实现无损准确率,同时在推理阶段利用BatchNorm的高效优势。此外,论文设计了一种简化的线性注意力机制,其在计算成本较低的情况下达到
SLAB:华为开源,通过线性注意力和PRepBN提升Transformer效率 | ICML 2024 SLAB:华为开源,通过线性注意力和PRepBN提升Transformer效率 | ICML 2024 SLAB:华为开源,通过线性注意力和PRepBN提升Transformer效率 | ICML 2024
[VS Code扩展]写一个代码片段管理插件(二):功能实现
@目录创建和插入代码片段代码片段列表代码片段预览代码片段编辑自定义映射默认映射自动完成项目地址 创建和插入代码片段 VS Code扩展提供了数据存储,其中globalState是使用全局存储的Key-Value方式来保存用户状态,支持在不同计算机上保留某些用户状态,详情请参考官方文档 若在编辑器区域
[VS Code扩展]写一个代码片段管理插件(二):功能实现 [VS Code扩展]写一个代码片段管理插件(二):功能实现 [VS Code扩展]写一个代码片段管理插件(二):功能实现