【问题标题】:How to remove YAML frontmatter from markdown files?如何从 markdown 文件中删除 YAML frontmatter?
【发布时间】:2015-03-29 02:18:01
【问题描述】:

我有包含 YAML 前端元数据的降价文件,如下所示:

---
title: Something Somethingelse
author: Somebody Sometheson 
---

但 YAML 具有不同的宽度。我可以使用像sed 这样的Posix 命令来删除位于文件开头的frontmatter 吗?只是删除 ------ 之间的所有内容,包括在内,但也会忽略文件的其余部分,以防其他地方有 ---s。

【问题讨论】:

  • 你能指定输入和输出吗?我的理解是你想删除------ 中的行。如果是这样,请尝试sed -i -n '/---/,/---/d' [file]
  • qqibrow,您所写的sed 命令过于贪婪,会删除比所要求的更多的内容。

标签: text-processing


【解决方案1】:

如果你不介意“或某事”是 perl。

在找到两个“---”实例后简单地打印:

perl -ne 'if ($i > 1) { print } else { /^---/ && $i++ }' yaml

如果你不介意滥用的话,或者更短一点?:用于流量控制:

perl -ne '$i > 1 ? print : /^---/ && $i++' yaml

如果要替换内联,请务必包含 -i

【讨论】:

    【解决方案2】:

    我理解你的问题意味着你想删除第一个----enclosed 块,如果它从第一行开始。在这种情况下,

    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 左右开头的行,您可能需要稍微更改模式(可能在末尾添加$ 以仅在整行为--- 时匹配) .我有点不清楚你的确切要求。

    【讨论】:

      【解决方案3】:

      如果您只想删除前面的内容,您可以简单地运行:

      sed '1{/^---$/!q;};1,/^---$/d' infile
      

      如果第一行不匹配---sedquit;否则它将delete 从1st 行到(包括)与--- 匹配的下一行(即整个前面的内容)的所有内容。

      【讨论】:

      • 因为前面的内容也可以以... 而不是--- 结尾,您可能希望将--- 的第二次出现替换为\(---\|\.\.\.\)
      • 如果输入文件没有front-matter,这个解决方案将文件减少到它的第一行 -> 不好!
      【解决方案4】:

      您使用 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: "\1"/' $f
          #...
      done
      

      【讨论】:

        【解决方案5】:

        这个基于 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 $0` -h"
            echo "    `basename $0` --help"
            echo "    `basename $0` -i <file-with-front-matter>"
            echo "    `basename $0` --in-place <file-with-front-matter>"
            echo "    `basename $0` <file-with-front-matter> <file-to-be-without-front-matter>"
        }
        
        replace=false
        in_file="-"
        out_file="/dev/stdout"
        
        if [ -n "$1" ]
        then
            if [ "$1" = "-h" ] || [ "$1" = "--help" ]
            then
                print_help
                exit 0
            elif [ "$1" = "-i" ] || [ "$1" = "--in-place" ]
            then
                replace=true
                in_file="$2"
                out_file="$in_file"
            else
                in_file="$1"
                if [ -n "$2" ]
                then
                    out_file="$2"
                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 $0;
            }
        }
        /^(---|...)$/ {
            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
        

        【讨论】:

          猜你喜欢
          • 2016-08-25
          • 2013-02-18
          • 2021-08-30
          • 1970-01-01
          • 2021-08-31
          • 2019-12-01
          • 2018-07-21
          • 2018-04-07
          • 2020-10-07
          相关资源
          最近更新 更多