SED/AWK:将字符串添加到与另一个源文件中的正则表达式值匹配的多个文件

SED/AWK:将字符串添加到与另一个源文件中的正则表达式值匹配的多个文件

我有一个源文件,其中包含以下格式的多个条目:

some_id: some string

以及不同文件夹中的一堆.txt文件,其中包含由 id 标识的字符串

id="some_id"

如何以某种方式解析源文件,以便.txt文件中具有id匹配源文件之一的每个字符串都添加一个新参数,如下所示

id="some_id" some_param="some string"

取自相应源文件 ID 的值

笔记

  • 同一个文件中可以有多个ID
  • 任何文件中都不会出现重复的 ID
  • 它们永远不会位于同一条线上
  • some_param是一个字面意思
  • some_param="string"只要在同一行并间隔开即可在哪里添加新内容并不重要

一些样本

源文件.yml

apples: Apples are very tasty
grapes: Grapes kind of ok
trees: Gain mass from CO2
strawberry: Yummy

水果/foo.txt

This is some plain text
Toreplace id="apples" string contains
The most vitamin-rich berry is id="strawberry"

水果/奇怪/葡萄.txt

And id="grapes" the

有问题/trees.txt

Or id="tress"

鉴于此示例,脚本应该变成水果/foo.txt进入:

This is some plain text
Toreplace id="apples" string contains some_param="Apples are very tasty"
The most vitamin-rich berry is id="strawberry" some_param="Yummy"

答案1

复杂的Grep+ GNUAwk解决方案:

关键的awk脚本内容,比方说add_param_by_id.awk

#!/bin/awk -f
BEGIN{ FS=":[[:space:]]+" }
NR==FNR{ a[$1] = $2; next }
match($0, /\<id="([^"]+)"/, b) && b[1] in a{ 
    sub(/\<id="[^"]+"/, "& some_param=\042"a[b[1]]"\042") 
}1

主要命令:

export pat="($(cut -d':' -f1 source.yml | paste -s -d'|'))"
grep -ElZr "\<id=\"$pat\"" --include=*.txt | xargs -0 -I{} sh -c \
'awk -f add_param_by_id.awk source.yml "$1" > "/tmp/$$" && mv "/tmp/$$" "$1"' _ {} 

  • pat- 包含带有标识符的正则表达式交替组的变量,即(apples|grapes|trees|strawberry)
  • grep -ElZr id=\"$pat\" --include=*.txt- 打印与任何指定标识符匹配的所有文件名

处理后的示例文件内容:

This is some plain text
Toreplace string contains id="apples" some_param="Apples are very tasty"
The most vitamin-rich berry is id="strawberry" some_param="Yummy"

答案2

带有某些警告,例如“文件名中没有奇怪的字符”和“/匹配或替换数据值中没有字符”,这应该适合您。它的效率不是很高,因为它会遍历 YAML 文件中每一行可以找到的每个文件,但为了解决这个问题,我需要更多有关 YAML 文件相对大小与目标文件数量的信息。

while IFS=: read -r id sp
do
    id="id=\"$id\"" sp="some_param=\"${sp:1}\""

    find . -type f -name '*.txt' |
        while IFS= read -r file
        do
            sed -i "/\<$id/s/$/ $sp/" "$file"
        done
done <source.yml

相关内容