
다음과 같은 섹션이 포함된 YAML 파일이 있습니다.
admin::common::passwords:
alice:
password: '$6$oTQhLvN/4VFJPscD$8LYwUMSFi'
bob:
password: '$6$JKOtLF0wHeZfIskt$W/M5.ugDS'
셸 변수 $ACCOUNT에 계정 이름(alice, bob 등)이 포함되어 있고 $YAML이 YAML 파일의 파일 이름인 경우 아래와 같이 sed를 사용하여 새 항목을 추가할 수 있습니다. "admin::common::passwords:" 줄 바로 아래에 새 계정이 삽입되므로 해당 계정이 올바른 섹션에 있다는 것을 알 수 있습니다.
sed -i /'^admin::common::passwords:'/a"\ ${ACCOUNT}:\n password: '${ENCRYPTED_PASS}'" $YAML
awk를 사용하여 이와 같은 기존 계정을 찾을 수 있습니다. 이번에도 섹션을 찾은 다음 해당 섹션 내의 계정을 찾습니다(awk에서 이 작업을 수행하는 것이 가능할 수도 있지만 awk로는 충분하지 않으므로 이 작업을 수행합니다).
awk "BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/admin::common::passwords:/" $YAML | grep -A1 "^[ ]*${ACCOUNT}:"
하지만 행을 삭제하려면 내가 생각할 수 있는 최선의 방법은 다음과 같습니다.
sed -i "/^ ${ACCOUNT}:/,+1d" $YAML
이렇게 하면 admin::common::passwords 섹션이든 다른 곳에 있든 파일의 모든 "^alice:" 줄이 제거됩니다.
파일에 admin::common:passwords 섹션이 포함되어 있다는 것 외에는 파일 내용에 대해 어떤 가정도 할 수 없습니다(그렇지 않으면 내 스크립트의 다른 부분에 의해 생성될 것입니다. 해당 비트는 단순한).
그래서 내 질문은: sed 측면에서 이것을 어떻게 개선할 수 있습니까?"^${ACCOUNT}:" 검색admin::common::passwords 섹션에서을 누른 다음 일치하는 줄과 그 아래 줄을 삭제하세요.'?
(물론 sed를 사용할 필요는 없습니다. awk 또는 심지어 Perl이 작업에 더 적합할 수도 있습니다.)
답변1
sed "
/^admin::common::passwords:$/,/^[^ ].*:$/ {
/^ $ACCOUNT:$/ {
N;d
}
}" < "$YAML"
즉, 삭제된 섹션을 admin::common...
다음 섹션과 일치하는 섹션 에 포함시킵니다 whatever-section:
.
사용자 이름에 흔히 사용되는 문자 .
도 정규식 연산자이므로 와 john.doe
일치 john.doe
하지만 johnWdoe
예를 들어 .
admin::common::passwords
두 개의 연속 섹션이 있고 삭제하려는 계정이 두 번째 섹션에 있는 경우 위 방법이 작동하지 않습니다.
만약에,오시우스가 지적했듯이, 섹션은 동일하거나 더 적은 수의 선행 공백 문자를 사용하여 다음 줄로 실행되며 섹션에 admin::common::passwords:
선행 공백이 있을 수 있습니다. 그러면 다른 언어로 전환해야 할 때가 될 수 있습니다 awk
. 예를 들면 다음과 같습니다.
awk -v account="$ACCOUNT" '
match($0, /[^ ]/) && RSTART <= n {n = 0}
n && NF == 1 && $1 == account ":" {getline; next}
!n && /^ *admin::common::passwords:$/ {
match($0, /[^ ]/)
n = RSTART
}
{print}' < "$YAML"
답변2
전체 파일을 구문 분석하기 위해 미리 만들어진 라이브러리를 사용하는 것이 더 안전할 것입니다(예: 다음과 같습니다).https://stackoverflow.com/questions/1773805/how-can-i-parse-a-yaml-file)을 클릭하여 변경한 다음 수정된 파일을 다시 저장하세요. 이와 같이 구조화된 텍스트 파일에 블라인드 텍스트를 수정하면 문제가 발생할 뿐입니다.