문자열을 찾아 첫 번째 문자열을 찾은 후 다음 줄의 다른 문자열로 바꿉니다.

문자열을 찾아 첫 번째 문자열을 찾은 후 다음 줄의 다른 문자열로 바꿉니다.

다음 내용을 포함하는 파일이 제공됩니다.

pkg1:
  replicaCount: 1
  image:
    tag: latest
    pullPolicy: Always

pkg2:
  replicaCount: 2
  image:
    tag: latest
    pullPolicy: Always

tag특정 패키지(예: )에 추가된 내용을 검색 하고 다른 패키지(예: )로 pkg1바꾸면 다음과 같은 결과를 얻을 수 있습니다.latestjunk

pkg1:
  replicaCount: 1
  image:
    tag: junk
    pullPolicy: Always

pkg2:
  replicaCount: 2
  image:
    tag: latest
    pullPolicy: Always

이 게시물에 대한 답변에 감사드립니다(문자열을 찾고 첫 번째 문자열을 찾은 후 다른 문자열을 바꿉니다.) "ex"를 사용하여 이 작업을 수행할 수 있습니다.

printf "%s\n" "/pkg1//latest/s//junk/" x | ex info.txt;

그런데 문제는 "ex"가 없는 이미지에서 실행된다는 점이다.

"awk"로 이 작업을 수행할 수 있는 방법이 있나요? 나는 파일을 한 줄씩 읽고 그런 식으로 일부 작업을 수행할 수 있다고 생각하지만 더 쉬운 방법을 찾고 있었습니다. 한 줄이라면 문제가 없습니다. 이것이 첫 번째 발생인지 두 번째 발생인지 항상 가정할 수는 없습니다. 그래서 패키지 이름을 검색해서 해당 패키지의 태그만 교체하면 됩니다.

답변1

가장 쉬운 방법은 명령줄 YAML 파서를 사용하는 것입니다.

$ yq -y '.pkg1.image.tag |= "junk"' file
pkg1:
  replicaCount: 1
  image:
    tag: junk
    pullPolicy: Always
pkg2:
  replicaCount: 2
  image:
    tag: latest
    pullPolicy: Always

나는 그것을 사용하고 있습니다 yq,Andrei Kislyuk jqYAML 문서 래퍼(다른 도구 yq도 호출되므로 올바른 도구를 사용하는지 확인하세요.)

이 명령은 .pkg1.image.tag키 값을 string 으로 설정하고 junk, 이 -y옵션은 기본 JSON 대신 YAML 출력을 생성하는 데 사용됩니다.

yq나는 이것이 Debian 기반 Linux 배포판의 기본값이라고 생각합니다 . YAML 문서를 JSON으로 변환하고 jq다음을 사용하여 수정해야 합니다.

$ yq r -j file.yml | jq '.pkg1.image.tag |= "junk"' | yq r -P -
pkg1:
  replicaCount: 1
  image:
    tag: junk
    pullPolicy: Always
pkg2:
  replicaCount: 2
  image:
    tag: latest
    pullPolicy: Always

답변2

가능한 경우 perl:

PKG=pkg1 FIELD=tag VALUE=junk perl -pi -e '
  $pkg = $1 if /^(\S.*?)\s*:\s*$/;
  s/^\s+\Q$ENV{FIELD}\E\s*:\s*\K.*/$ENV{VALUE}/ if $pkg eq $ENV{PKG}' -- "$file"

최신 버전의 GNU 구현을 제외하고 awk파일의 내부 편집은 지원되지 않습니다 . 실제로 최근에 멍청한 사람 이라면 awk위와 동일한 작업을 수행할 수 있습니다.

PKG=pkg1 FIELD=tag VALUE=junk gawk -i /usr/share/awk/inplace.awk -e '
  match($0, /^([^[:space:]](.*[^[:space:]])?)[[:space:]]*:[[:space:]]*$/, f) {
   pkg = f[1] ""
 }
 pkg == ENVIRON["PKG"] {
   $0 = gensub("^([[:space:]]+"ENVIRON["FIELD"]"[[:space:]]*:[[:space:]]*).*", \
               "\\1" ENVIRON["VALUE"], 1)
 }
 {print}' -E /dev/null "$file"

awk저는 API 의 몇 가지 제한 사항과 주의 사항을 해결하려고 노력합니다 awk.

  • -v var=value맹글 백슬래시 방법을 사용하여 매개변수를 환경 변수로 전달합니다.
  • pkg = f[i] "": 비교가 항상 문자열 비교인지 확인하기 위해 ""문자열로 처리되도록 a를 추가합니다( 아니요 대).pkgawk==eqperl
  • -e 'code' -E /dev/null "$file"(GNU 확장) 임의의 파일 이름을 처리하는 데 필요합니다.

하지만 일부 남아 있는 부분이 있는데, 이는 특정 입력에 대한 특수한 경우에는 여전히 제대로 작동하지 않는다는 것을 의미합니다.

  • perl/ 와 동등한 것이 없으므로 \Qawk 정규식 연산자(char)를 포함하면 \E작동하지 않습니다.FIELD.^${}[]\?+*|
  • VALUE대체 매개변수에서 또는 포함 &문자가 특별히 처리 되면 \올바르게 작동하지 않습니다 .gawkgensub()

^사용하지 마세요-i inplace현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

관련 정보