次の形式の複数の項目を含むソースファイルがあります。
some_id: some string
.txt
IDで識別される文字列を含む複数のフォルダにある複数のファイル
id="some_id"
ソースファイルの1つに一致する.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