如何使用 awk 提取 YAML 元数据块

如何使用 awk 提取 YAML 元数据块

我有许多 Markdown 文件,顶部有一个 YAML 元数据块:

---
title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false
---

**title**

a piece of indertimate  
length that could be a few lines of many hundreds

---[author name](author link)
---found in [source](source link)

我正在尝试找到一种提取元数据块的方法(这样我可以将其输入到yamllint,但后来也可以输入其他内容)。 awk 似乎是正确的工具,但是当我不理解 awk 时,我想出的最好的方法是:

awk '/^---$/ {printline = 1; print; next} /^---$/ {printline = 0} printline'

这只是显示了整个文件,我尝试限制---它们自己的行是行不通的(也许这里没有其他的)!

答案1

sed可能是更好的工具选择。由于它始终位于文件的顶部,因此您可以指定sed只打印从第 2 行到该---行的内容,然后删除该行。

例如

sed -n '2,/^---$/ {/^---$/d; p}'

这是通过以下方式实现的:

-n: don't print by default
2,/^---$/ { ... }: limit the next part to the lines between line 2 and the first line matching ---

然后在那个街区内

/^----$/d : delete the --- line
p : print what remains.

所以在你的测试文件中输出是

title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false

要做到这一点awk需要跟踪状态。例如

awk '
/^---$/ && printline==0 {printline = 1;next}
/^---$/ {printline = 2; next}
{ if (printline==1) { print } }
'

---如果文件的其余部分中有一行,则需要此状态。

答案2

由于元数据块是由---分隔符分隔的,因此我们可以将记录分隔符/设置RS为此。

假设元数据块始终位于 yaml 文件的开头并用 分隔---,则可以安全地假设第二条记录将是元数据块,因此我们可以说:

➜ awk 'BEGIN { RS = "---" } NR==2' example-yaml.txt 

title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false

来提取它。

awk默认使用换行符作为记录分隔符,但是(至少在 GNU awk 中,其他 awk 实现可能有所不同,因为我除了 gawk 之外还没有验证这一点)它可以设置为任何/多个字符以及正则表达式(请参阅awk 分割记录(GNU Awk 用户指南)以供参考)。

答案3

使用编辑器删除从第二个 YAML 文档分隔---符到文档末尾的所有内容,然后显示剩余内容:

$ printf '%s\n' '1;/^---$/,$d' ,p Q | ed -s file
---
title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false

反转所有行,删除第一个---分隔符(这将是 YAML 部分末尾的分隔符),然后再次反转行:

$ tail -r file | sed '1,/^---$/d' | tail -r
---
title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false

如果您的实施没有-r选项(在 macOS 和其他 BSD 系统上可用),您可以使用 GNU反而。

答案4

$ awk 'BEGIN{printline=2} /^---$/{printline--; next} printline' file.yaml
title: title of work
author: author name
author-sort: name, author
published: N
date: XXXX-XX-XX
pub-number: XXXXX
embedded-title: false

printline命令末尾是一种打印语句,就正awk整数的默认行为是打印整行。一开始,该printline变量设置为 2,然后每次正则表达式^---$匹配时递减。所以当printline为零时,awk停止打印。

相关内容