我有一个源文件,其中包含以下格式的多个条目:
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