【问题标题】:Replace multi-line plain text替换多行纯文本
【发布时间】:2018-07-18 04:01:07
【问题描述】:

假设您有大量 yaml 文件(或任何类似文件),并且您想为所有具有给定名称的对象添加描述,例如

- name: alan
  age: 8

- name: britney # some comment about britney
  hobbies: ["painting", "CS"]
  age: 21

- name: charles # some comment about charles
                # that spans over multiple lines
  age: 42

我有一个需要描述名称的对象列表,例如

britney: teamblue
charles: foobar

如何添加带有描述的行以达到以下目的:

- name: alan
  age: 8

- name: britney # some comment about britney
  hobbies: ["painting", "CS"]
  age: 21
  description: teamblue

- name: charles # some comment about charles
                # that spans over multiple lines
  age: 42
  description: foobar

到目前为止,我已经很接近了,但我总是无法用另一个纯文本替换多行文本:

s=$(awk "/${name}/" RS= ./*.yml)
r=$(awk "/${name}/" RS= ./*.yml && echo "  description: ${desc}")

我需要以某种方式寻找$s 并将其替换为$r,但我无法使其工作。我尝试了以下两种的多种变体:

sed "s/$s/$r/" ./*.yml
perl -i -0pe "s/$s/$r/" ./*.yml

但不知何故,yaml 中的特殊字符(换行符、双引号等)会破坏它们,我要么收到类似 unterminated substitute pattern 的错误消息,要么输出相同,但没有匹配。

也可能与sed 相关,我使用的是 macOS。

【问题讨论】:

  • 使用 YAML 解析器。
  • 使用解析器,我想我会丢失文件中的所有 cmets 和格式。
  • 哪种格式? YAML 是一种机器可读的格式。格式无关紧要。我相信应该有一个理解 cmets 的解析器。我敢肯定,很快就会有更多 YAML 知识的人出现。但是在没有解析器的情况下这样做意味着您必须构建自己的解析器。
  • 为什么hobbies的行下移了?
  • @ATN, Re "我不需要解析器",根据定义,你需要一个解析器。您要编写的是解析器。问题是您正在编写的解析器很糟糕。更糟糕的是,您暗示这是手写的 YAML,因此用户可以提供任何合法的 YAML,而所提供的答案都无法做到这一点。你知道有效的 JSON 就是有效的 YAML 吗?

标签: perl sed replace yaml


【解决方案1】:
$ cat tst.awk
NR==FNR {
    sub(/:/,"",$1)
    map[$1] = $2
    next
}
$3 in map {
    $0 = $0 "\n  description: " map[$3]
}
{ print }

.

$ awk -f tst.awk list RS= ORS='\n\n' foo.yaml
- name: alan
  age: 8

- name: britney # some comment about britney
  hobbies: ["painting", "CS"]
  age: 21
  description: teamblue

- name: charles # some comment about charles
                # that spans over multiple lines
  age: 42
  description: foobar

上面使用了这些输入文件:

$ cat list
britney: teamblue
charles: foobar

.

$ cat foo.yaml
- name: alan
  age: 8

- name: britney # some comment about britney
  hobbies: ["painting", "CS"]
  age: 21

- name: charles # some comment about charles
                # that spans over multiple lines
  age: 42

【讨论】:

  • @ghoti:这与问题完全无关。为什么会有人想了解你的午餐?
【解决方案2】:
$ awk 'FNR==NR{a[$1]=$2; next} ($3":" in a){sub(/$/,"\n  description: "a[$3":"])}1' list RS= ORS="\n\n" file.yaml

FNR==NR{a[$1]=$2; next} :在读取文件list 时,创建一个关联数组a,其键为$1,值为$2。例如。 a[britney:]=teamblue

($3":" in a){sub(/$/,"\n description: "a[$3":"])}1:读取文件file.yaml时,如果$3":"a中的key,则在打印前在记录中追加description

输出

- name: alan
  age: 8

- name: britney # some comment about britney
  hobbies: ["painting", "CS"]
  age: 21
  description: teamblue

- name: charles # some comment about charles
                # that spans over multiple lines
  age: 42
  description: foobar

【讨论】:

  • 这样的awk是我晚上可以睡觉的原因。
  • @zzxyz:对不起,我没有得到。是褒义词还是反义词? :P
  • 恭维 :) 这真的很漂亮。
猜你喜欢
  • 1970-01-01
  • 2018-03-26
  • 2022-10-06
  • 2020-02-27
  • 2010-09-18
  • 2017-10-23
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多