SED/AWK: 다른 소스 파일의 정규식 값과 일치하는 여러 파일에 문자열 추가

SED/AWK: 다른 소스 파일의 정규식 값과 일치하는 여러 파일에 문자열 추가

다음 형식의 여러 항목이 포함된 소스 파일이 있습니다.

some_id: some string

.txtID로 식별되는 문자열을 포함하는 여러 폴더에 있는 여러 파일

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

관련 정보