如何从降价文件中删除 YAML frontmatter?
How to remove YAML frontmatter from markdown files?
我有包含 YAML frontmatter 元数据的降价文件,如下所示:
---
title: Something Somethingelse
author: Somebody Sometheson
---
但是 YAML 的宽度不同。我可以使用像 sed
这样的 Posix 命令来删除位于文件开头的 frontmatter 吗?只是删除 ---
和 ---
之间的所有内容,包括在内,但也会忽略文件的其余部分,以防其他地方有 ---
。
如果您不介意 "or something" 是 perl。
找到两个“---”实例后简单地打印:
perl -ne 'if ($i > 1) { print } else { /^---/ && $i++ }' yaml
如果您不介意滥用 ?: 用于流量控制,或者更短一些:
perl -ne '$i > 1 ? print : /^---/ && $i++' yaml
如果要替换内联,请务必包含 -i
。
我理解你的问题的意思是你想删除第一个 ---
封闭的块,如果它从第一行开始的话。那样的话,
sed '1 { /^---/ { :a N; /\n---/! ba; d} }' filename
这是:
1 { # in the first line
/^---/ { # if it starts with ---
:a # jump label for looping
N # fetch the next line, append to pattern space
/\n---/! ba; # if the result does not contain \n--- (that is, if the last
# fetched line does not begin with ---), go back to :a
d # then delete the whole thing.
}
}
# otherwise drop off the end here and do the default (print
# the line)
根据您希望如何处理以 ---abc
左右开头的行,您可能需要稍微更改模式(也许在末尾添加 $
以仅在整个行是 ---
)。我不太清楚你那里的具体要求。
如果你只想删除前面的内容,你可以简单地 运行:
sed '1{/^---$/!q;};1,/^---$/d' infile
如果第一行不匹配---
,sed
将q
退出;否则它将 d
删除从第 1
行到(并包括)与 ---
匹配的下一行(即整个前面的内容)的所有内容。
您使用 bash 文件,创建 script.sh
并使用 chmod +x script.sh
和 运行 使其可执行 ./script.sh
.
#!/bin/bash
#folder articles contains a lot of markdown files
files=./articles/*.md
for f in $files;
do
#filename
echo "${f##*/}"
#replace frontmatter title attribute to "title"
sed -i -r 's/^title: (.*)$/title: ""/' $f
#...
done
这个基于 AWK 的解决方案适用于有和没有 FrontMatter 的文件,在后一种情况下什么都不做。
#!/bin/sh
# Strips YAML FrontMattter from a file (usually Markdown).
# Exit immediately on each error and unset variable;
# see: https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
set -Ee
print_help() {
echo "Strips YAML FrontMattter from a file (usually Markdown)."
echo
echo "Usage:"
echo " `basename [=10=]` -h"
echo " `basename [=10=]` --help"
echo " `basename [=10=]` -i <file-with-front-matter>"
echo " `basename [=10=]` --in-place <file-with-front-matter>"
echo " `basename [=10=]` <file-with-front-matter> <file-to-be-without-front-matter>"
}
replace=false
in_file="-"
out_file="/dev/stdout"
if [ -n "" ]
then
if [ "" = "-h" ] || [ "" = "--help" ]
then
print_help
exit 0
elif [ "" = "-i" ] || [ "" = "--in-place" ]
then
replace=true
in_file=""
out_file="$in_file"
else
in_file=""
if [ -n "" ]
then
out_file=""
fi
fi
fi
tmp_out_file="$out_file"
if $replace
then
tmp_out_file="${in_file}_tmp"
fi
awk -e '
BEGIN {
is_first_line=1;
in_fm=0;
}
/^---$/ {
if (is_first_line) {
in_fm=1;
}
}
{
if (! in_fm) {
print [=10=];
}
}
/^(---|...)$/ {
if (! is_first_line) {
in_fm=0;
}
is_first_line=0;
}
' "$in_file" >> "$tmp_out_file"
if $replace
then
mv "$tmp_out_file" "$out_file"
fi
我有包含 YAML frontmatter 元数据的降价文件,如下所示:
---
title: Something Somethingelse
author: Somebody Sometheson
---
但是 YAML 的宽度不同。我可以使用像 sed
这样的 Posix 命令来删除位于文件开头的 frontmatter 吗?只是删除 ---
和 ---
之间的所有内容,包括在内,但也会忽略文件的其余部分,以防其他地方有 ---
。
如果您不介意 "or something" 是 perl。
找到两个“---”实例后简单地打印:
perl -ne 'if ($i > 1) { print } else { /^---/ && $i++ }' yaml
如果您不介意滥用 ?: 用于流量控制,或者更短一些:
perl -ne '$i > 1 ? print : /^---/ && $i++' yaml
如果要替换内联,请务必包含 -i
。
我理解你的问题的意思是你想删除第一个 ---
封闭的块,如果它从第一行开始的话。那样的话,
sed '1 { /^---/ { :a N; /\n---/! ba; d} }' filename
这是:
1 { # in the first line
/^---/ { # if it starts with ---
:a # jump label for looping
N # fetch the next line, append to pattern space
/\n---/! ba; # if the result does not contain \n--- (that is, if the last
# fetched line does not begin with ---), go back to :a
d # then delete the whole thing.
}
}
# otherwise drop off the end here and do the default (print
# the line)
根据您希望如何处理以 ---abc
左右开头的行,您可能需要稍微更改模式(也许在末尾添加 $
以仅在整个行是 ---
)。我不太清楚你那里的具体要求。
如果你只想删除前面的内容,你可以简单地 运行:
sed '1{/^---$/!q;};1,/^---$/d' infile
如果第一行不匹配---
,sed
将q
退出;否则它将 d
删除从第 1
行到(并包括)与 ---
匹配的下一行(即整个前面的内容)的所有内容。
您使用 bash 文件,创建 script.sh
并使用 chmod +x script.sh
和 运行 使其可执行 ./script.sh
.
#!/bin/bash
#folder articles contains a lot of markdown files
files=./articles/*.md
for f in $files;
do
#filename
echo "${f##*/}"
#replace frontmatter title attribute to "title"
sed -i -r 's/^title: (.*)$/title: ""/' $f
#...
done
这个基于 AWK 的解决方案适用于有和没有 FrontMatter 的文件,在后一种情况下什么都不做。
#!/bin/sh
# Strips YAML FrontMattter from a file (usually Markdown).
# Exit immediately on each error and unset variable;
# see: https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/
set -Ee
print_help() {
echo "Strips YAML FrontMattter from a file (usually Markdown)."
echo
echo "Usage:"
echo " `basename [=10=]` -h"
echo " `basename [=10=]` --help"
echo " `basename [=10=]` -i <file-with-front-matter>"
echo " `basename [=10=]` --in-place <file-with-front-matter>"
echo " `basename [=10=]` <file-with-front-matter> <file-to-be-without-front-matter>"
}
replace=false
in_file="-"
out_file="/dev/stdout"
if [ -n "" ]
then
if [ "" = "-h" ] || [ "" = "--help" ]
then
print_help
exit 0
elif [ "" = "-i" ] || [ "" = "--in-place" ]
then
replace=true
in_file=""
out_file="$in_file"
else
in_file=""
if [ -n "" ]
then
out_file=""
fi
fi
fi
tmp_out_file="$out_file"
if $replace
then
tmp_out_file="${in_file}_tmp"
fi
awk -e '
BEGIN {
is_first_line=1;
in_fm=0;
}
/^---$/ {
if (is_first_line) {
in_fm=1;
}
}
{
if (! in_fm) {
print [=10=];
}
}
/^(---|...)$/ {
if (! is_first_line) {
in_fm=0;
}
is_first_line=0;
}
' "$in_file" >> "$tmp_out_file"
if $replace
then
mv "$tmp_out_file" "$out_file"
fi