之前折腾 GtiHub Actions 想实现提交 issue 后将 issue 的内容生成一个 Markdown 文件提交到仓库,从而实现自动发布到 GitHub Pages 的目的。倒是有一些现成的 Action,但无法完全满足要求,所以自己尝试写一个 wayou/turn-issues-to-posts-action

过程中发现因为 issue 的标题和正文是任意的,也就是以下两部分:

  • github.event.issue.title
  • github.event.issue.body

分别通过环境变量 github.event.issue 获取。

当然,做成 Action 后这些参数通过外面以参数方式传递,因为 Action 里无法获取这些数据。

使用该 Action 的仓库中,.github/workflows/main.yml 配置如下内容进行传递:

...
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: wayou/turn-issues-to-posts-action@v1
with:
dir: "_posts"
title: ${{ github.event.issue.title }}
body: ${{ github.event.issue.body }}
...

里面的内容可能包含任意字符,这样在生成文章标题和正文时会遇到转义问题。

mkdir 创建目录失败的失败

生成的文件默认放到 _posts/ 目录下,但也可以使用的地方进行传递。

mkdir ${{ inputs.dir }}

生成目录过程中,_posts/ 目录不存在的话,该命令会失败,所以需要加上 -p 参数。man mkdir 查看可知:

     -p      Create intermediate directories as required.  If this option is not speci-
fied, the full path prefix of each operand must already exist. On the other
hand, with this option specified, no error will be reported if a directory
given as an operand already exists. Intermediate directories are created
with permission bits of rwxrwxrwx (0777) as modified by the current umask,
plus write and search permission for the owner.

加了该参数后,mkdir 会自动创建缺失的目录而不是直接报错。

标题

然后通过标题创建对应的 Markdown 文件。

touch "${{ inputs.title }}.md"

直接像上面这样肯定不行,因为前面提到,这里的 title 可能包含任意字符。所以需要对 issue 的 title 进行一次处理。

POST_TITLE=$(sed -E 's/[[:space:]|[:punct:]]/_/g' <<<'${{ inputs.title }}')

上述操作是替换掉 issue 标题中的空格及标点。

正文

同时,正文部分也不能直接通过如下方式进行写入:

cat "${{ inputs.body }}" >> "${{ inputs.title }}.md"

一是因为正文是多行文本,这里 Action 执行时会被替换为真实的内容,到时候就是非法的 shell 命令,二是因为正文也会包含任意字符,造成命令非法。

后面发现,可通过如下形式进行文件创建和内容的写入而没有上面这些因为内容而引起的转义问题:

              <<[-]word
here-document
delimiter

可通过 man bash 查看该形式的文档,位于 Here Documents 部分。

调整后文件生成及内容生成部分的命令为

        cat <<'EOF' > _posts/"${DATE:0:10}-${POST_TITLE}".md
---
layout: post
title: "${{ inputs.title }}"
date: ${{ inputs.created_at }}
---
${{ inputs.body }}
EOF

不过仍然需要处理两处转义问题:

  • _posts/"${DATE:0:10}-${POST_TITLE}".md 这里的 "${DATE:0:10}-${POST_TITLE}" 部分需要使用引号包裹,防止我死字符导致的文件名非法
  • title: "${{ inputs.title }}" 这部分位于 Markdown 文件正文部分,会被 jekyll 编译后生成对应的 html 文件,这里不使用引号的话,jekyll 编译会有问题,比如标题中包含 backtick `
---
layout: post
title: `/dev/null`
date: 2020-08-11 23:08:00 +0800
tags:
---

jekyll 报错信息:

Error: YAML Exception reading xxx/_posts/2020-12-25-xxx.md: (<unknown>): found character that cannot start any token while scanning for the next token at line 3 column 8

相关资源

The text was updated successfully, but these errors were encountered:

shell 使用 cat 配合 EOF 创建文件并写入多行内容的更多相关文章

  1. Linux下巧用cat与EOF实现文件的替换和追加

    本文地址http://comexchan.cnblogs.com/,作者Comex Chan,尊重知识产权,转载请注明出处,谢谢! ================================== ...

  2. 【HDFS API编程】查看HDFS文件内容、创建文件并写入内容、更改文件名

    首先,重点重复重复再重复: /** * 使用Java API操作HDFS文件系统 * 关键点: * 1)创建 Configuration * 2)获取 FileSystem * 3)...剩下的就是 ...

  3. python之模块csv之CSV文件的写入(按行写入)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #CSV文件的写入(按行写入) import csv #csv文件,是一种常用的文本格式,用以存储表格数据,很 ...

  4. rev---将文件中的每行内容以字符为单位反序输出

    rev命令将文件中的每行内容以字符为单位反序输出,即第一个字符最后输出,最后一个字符最先输出,依次类推.

  5. php学习笔记--高级教程--读取文件、创建文件、写入文件

    打开文件:fopen:fopen(filename,mode);//fopen("test.txt","r"): 打开模式:r  仅仅读方式打开,将文件指针指向 ...

  6. java io流 创建文件、写入数据、设置输出位置

    java io流 创建文件 写入数据 改变system.out.print的输出位置 //创建文件 //写入数据 //改变system.out.print的输出位置 import java.io.*; ...

  7. 使用IO流创建文件并写入数据

    /* 字符流和字节流: 字节流两个基类: InputStream OutputStream 字符流两个基类: Reader Writer 既然IO流是用于操作数据的, 那么数据的最常见体现形式是:文件 ...

  8. HDFS上创建文件、写入内容

    1.创建文件 hdfs dfs -touchz /aaa/aa.txt 2.写入内容 echo "<Text to append>" | hdfs dfs -appen ...

  9. Java之创建文件并写入数据

    应用场景:以OJ项目为例,创建对应的.in或.out文件,并将相关的数据写入. 核心代码如下: /** * 创建文件 * @param data * @param basedir * @param n ...

随机推荐

  1. 将AOSP源码导入到Android Studio进行查看

    生成iml和ipr文件 source build/envsetup.sh lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target make idegen deve ...

  2. [Python] 茎叶图和复合饼图的画法

    目录 茎叶图 复合饼图 茎叶图 from itertools import groupby nums2=[225, 232,232,245,235,245,270,225,240,240,217,19 ...

  3. JS相关基础

    1. ES5和ES6继承方式区别 ES5定义类以函数形式, 以prototype来实现继承 ES6以class形式定义类, 以extend形式继承 2. Generator了解 ES6 提供的一种异步 ...

  4. HarmonyOS三方件开发指南(13)-SwipeLayout侧滑删除

    鸿蒙入门指南,小白速来!0基础学习路线分享,高效学习方法,重点答疑解惑--->[课程入口] 目录:1. SwipeLayout组件功能介绍2. SwipeLayout使用方法3. SwipeLa ...

  5. vue学习遇到的问题

    1.vue脚手架的安装,解决链接:https://www.cnblogs.com/qcq0703/p/14439467.html2.2.2.0+ 的版本里,当在组件上使用 v-for 时,key 现在 ...

  6. LinkedHashMap转对象

    当需要把map转为实体对象时,需要结合fastjson来实现,方法如下: LinkedHashMap<String,Object> hashMap = new LinkedHashMap& ...

  7. MySQL全面瓦解23:MySQL索引实现和使用

    MySQL索引实现 上一篇我们详细了解了B+树的实现原理(传送门).我们知道,MySQL内部索引是由不同的引擎实现的,主要包含InnoDB和MyISAM这两种,并且这两种引擎中的索引都是使用b+树的结 ...

  8. Numpy初体验

    目录 Numpy 一.简介 1.安装 2.特殊的导包 二.ndarray-多维数组对象 1.创建ndarray数组 1.1 array 1.2 arange 1.3 linspace 1.4 zero ...

  9. Docker的架构

    一.Docker引擎 docker引擎是一个c/s结构的应用,主要组件见下图: Server是一个常驻进程 REST API 实现了client和server间的交互协议 CLI 实现容器和镜像的管理 ...

  10. for、while的循环套用和函数的递归

    一.集成开发工具Eclipse 1.1 下载 官网下载 https://www.eclipse.org/downloads/download.php?file=/technology/epp/down ...