之前折腾 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. 全球首发—鸿蒙开源平台OpenGL

    目录: 前言 背景 鸿蒙OpenGL-ISRC的结构 OpenGL-ISRC和鸿蒙SDK OpenGL的区别 OpenGL-ISRC的使用 前言 基于安卓平台的OpenGL(androidxref.c ...

  2. RabbitMq手动确认时的重试机制

    本文转载自RabbitMq手动确认时的重试机制 消息手动确认模式的几点说明 监听的方法内部必须使用channel进行消息确认,包括消费成功或消费失败 如果不手动确认,也不抛出异常,消息不会自动重新推送 ...

  3. 使用RSEM进行转录组测序的差异表达分析

    仍然是两年前的笔记 1. prepare-reference 如果用RSEM对比对后的bam进行转录本定量,则在比对过程中要确保比对用到的索引是由rsem-prepare-reference产生的. ...

  4. AttributeError: 'function' object has no attribute 'as_view'

    我的描述:当我启用jwt_required来进行token验证的时候,我提示错误; 解决方案: 修改前代码: 修改后代码: 多看书.多多了解.多看看世界...

  5. 3分钟学会如何上手supervisor看门狗

    软硬件环境 centos7.6.1810 64bit cat /etc/redhat-release #查看系统版本 supervisor 3.4.0 python 2.7.5 supervisor简 ...

  6. SpringBoot Test 多线程报错:dataSource already closed

    1:前言 最近在项目中使用多线程对大任务拆分处理时,进行数据库操作的时候报错了. 业务代码大概是这样的: @Service public calss TestServiceImpl implement ...

  7. 第41天学习打卡(死锁 Lock synchronized与Lock的对比 线程协作 使用线程池)

    死锁 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形.某一个同步块同时拥有"两个以上对象的锁"时 ...

  8. Go benchmark 一清二楚

    前言 基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器. 在日常生活中,我们使用速度 m/s(单位时间内物体移动的距离)大小来衡量一辆跑车的性能,同理 ...

  9. LeetCode113. 路径总和 II

    原题链接 1 class Solution: 2 def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: 3 ans,tm ...

  10. 在C#的WPF程序使用XAML实现画线

    在WPF中画直线.新建WPF应用程序,使用XAML画直线.使用X1.Y1两个属性可以设置直线的起点坐标,X2.Y2两个属性则可以设置直线的终点坐标.控制起点/终点坐标就可以实现平行.交错等效果.Str ...