파일의 다른 특정 문자열 다음에 나오는 일치하는 문자열을 바꿉니다.

파일의 다른 특정 문자열 다음에 나오는 일치하는 문자열을 바꿉니다.

ssl.cfgSSL 요청에 대한 구성 파일( )이 있습니다.

oid_section = OIDs

[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn

attributes = v3_req

[OIDs]
OrganizationID = 2.5.4.97        # Don't touch this

[dn]
C = FO
ST = Foobar Monarchy
O = Lorem Ipsum
CN = specific.domain.com
OrganizationID = ABCDE-12345     # Change this
#...

[v3_req]
#...

교체하려고 해요두번째 OrganizationIDvalue( ABCDE-12345) 및 새 값 ABCDE-98765.

문제는 대부분이 OrganizationID동일해야 하는 두 개의 동일한 이름 사이의 충돌에 대해 객체를 일치시킨다는 것입니다(아래 부분 [OIDs]은 마크업 태그이고 두 번째 발생은 실제로사용상표).

내가 시도한 것들:

1) 이 답변에서 수정된 코드 (일치 후 줄 바꾸기) 스택 오버플로:

REQ_ID="ABCDE-98765"
sed -i "/CN =/!b;n;c\\OrganizationID = ${REQ_ID}" ssl.cfg
  • 이전 줄과 일치합니다.CN = ...
  • !b현재 경기 중단
  • n다음 줄 스캔
  • c선택한 줄을 다음 텍스트로 변경합니다( \새 줄 인쇄, \\큰따옴표( )로 인해 이스케이프됨)

나는 이 솔루션이 이전 행의 위치에 의존하기 때문에 별로 좋아하지 않습니다. 누군가 수동으로 CN을 다른 회선으로 바꾸면 문제가 발생합니다.

2) 이전 시도에서 얻은 지식을 활용합니다.

REQ_ID="ABCDE-98765"
sed -i "/\\\[dn\\\]/!b;/OrganizationID/c\\OrganizationID = ${REQ_ID}" ssl.cfg

여기서는 다음을 시도했습니다.

  • 일치 [dn](이중 이스케이프 [])
  • 현재 경기 중단
  • 이 지점부터 시작하여 다음 OrganizationID 항목을 찾습니다.
  • 대신 사용c\...

이것은 작동하지 않을 것입니다. 두 번째 게임이 처음부터 다시 시작될 것 같은 느낌이 듭니다. 두 항목이 모두 일치하면 아무 것도 바뀌지 않는 것 같습니다.

특히 [dn]의 위치에 관계없이 OrgID를 일치시키는 방법을 찾고 있습니다. 해당 값의 문자열은 ABCDE-변경되지 않을 수 있지만 이에 의존하고 싶지는 않습니다. 객체 식별자2.5.4.97 변하지 않을 것이다.

결론적으로:

  1. 특정 줄부터 시작하여 파일을 찾아볼 수 있는 방법이 있나요? ( [dn]태그 사용)
  2. 위의 목표를 달성할 수 있는 다른 방법이 있나요? ( awk? 다른 sysutils + 파이프?...)

(제목이 혼란스러워서 사과드립니다. 어떻게 표현해야 좋을지 모르겠습니다.)

답변1

$ awk -v org='ABCDE-12345' -v RS= -v ORS='\n\n' '
    $1 == "[dn]" {
        $0 = "\n" $0
        sub(/\nOrganizationID[[:space:]]*=[^\n]*/,"\nOrganizationID = " org)
        sub(/^\n/,"")
    }
    { print }
' file
oid_section = OIDs

[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn

attributes = v3_req

[OIDs]
OrganizationID = 2.5.4.97        # Don't touch this

[dn]
C = FO
ST = Foobar Monarchy
O = Lorem Ipsum
CN = specific.domain.com
OrganizationID = ABCDE-12345
#...

[v3_req]
#...

RS=<null>awk를 빈 줄로 구분된 단락 모드로 설정합니다 RS = ""(https://www.gnu.org/software/gawk/manual/gawk.html#Multiple-Line), ORS='\n\n'출력이 빈 줄로 구분되어 있는지 확인하고, $0 = "\n" $0레코드의 각 줄 앞에 개행 문자가 있는지 확인하여 레코드의 첫 번째 줄에서도 sub()주변 개행 문자의 후속 사용이 성공하도록 한 다음, 추가한 임시 항목을 제거하세요. 첫 번째 줄 줄 바꿈 단계.OrganizationIDsub(/^\n/,"")

답변2

다음 코드는 으로 시작하는 행의 값을 선택한 값 awk으로 변경 하지만 부분적으로만 변경하고 해당 키가 처음 나타날 때만 변경합니다.OrganizationID[dn]

awk -F'=' -v OFS='=' '$0=="[dn]"{f=1} (f)&&$1~/^OrganizationID/{$2="Something-New"; f=0} 1' ssl.cfg

교체 항목을 하드코딩하지 않으려면 다음과 같이 가져올 수 있습니다.

req_id="Something-New"
awk -F'=' -v OFS='=' -v repl="$req_id" '$0=="[dn]"{f=1} (f)&&$1~/^OrganizationID/{$2=repl; f=0} 1' ssl.cfg

(그러나 변수의 이스케이프 시퀀스는 에 의해 해석되므로 awk리터럴 백슬래시가 필요한 경우 특별한 예방 조치를 취해야 합니다.StackOverflow에 대한 답변입니다.더 읽어보시려면).

위의 코드는 다음을 수행합니다.

  • =입력( -F'=')과 출력( )을 필드 구분 기호로 처리 하므로 -v OFS='='내부적으로 행은 "열"로 분할되고 =출력 행은 둘 사이의 필드 항목을 연결하여 어셈블됩니다 =.

  • 현재 줄 전체( $0)에 섹션 헤더만 포함되어 있으면 [dn]플래그가 f1로 설정되어 올바른 섹션이 발견되었음을 나타냅니다.

  • 오른쪽 섹션에 있고 첫 번째 필드( $1즉, 첫 번째 필드 앞의 문자열 =)가 로 시작하는 경우 OrganizationID두 번째 필드( 즉, 첫 번째 필드 뒤의 문자열)가 콘텐츠 콘텐츠 $2로 대체됩니다.=awkrepl껍데기$req_id옵션 변수를 통해 -v repl="$req_id". 또한 플래그를 재설정하여 해당 value 의 다른 항목을 대체하지 않습니다 OrganizationID.

  • 1규칙 블록 외부의 "혼자"는 { ... }"현재 줄과 이전 규칙에 의해 수정된 모든 내용을 인쇄합니다"를 줄여서 표현한 것입니다. 이 메커니즘의 기본 아이디어는 실제로 어떤 조건이라도 명시할 수 있다는 것입니다.외부 규칙 블록값이 true0이 아니면 awk현재 줄이 인쇄됩니다(예를 들어 awk 'FNR==1'내부 줄 카운터가 해당 줄 FNR과만 같기 때문에 첫 번째 줄만 인쇄됩니다 1).

    규칙 블록 내에 명시적인 print/ 명령이 없거나 다음과 같이 평가되는 "전역" 조건이 있는 경우printftrueawk아니요현재 줄을 인쇄합니다.

귀하의 예 출력 :

oid_section = OIDs

[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn

attributes = v3_req

[OIDs]
OrganizationID = 2.5.4.97        # Don't touch this

[dn]
C = FO
ST = Foobar Monarchy
O = Lorem Ipsum
CN = specific.domain.com
OrganizationID =Something-New
#...

[v3_req]

이 코드는 파일을 수정하지는 않지만 결과를 콘솔에 출력합니다(그래서 먼저 올바른지 확인할 수 있습니다). 만족스러우면 출력을 새 파일로 리디렉션하고 수동으로 바꿀 수 있습니다. 또는 지원하는 경우 확장 기능(최근 GNU 구현의 경우 )을 awk사용할 수 있습니다 .-i inplaceawk

awk -F"=" -v OFS="=" '.. etc ..' ssl.cfg > ssl.cfg.new

또는

awk -i inplace -F"=" -v OFS="=" '.. etc ..' ssl.cfg

답변3

방법 1

for  i in `sed -n '/OrganizationID/{;=;}' file| sed -n '2p'`; do sed ''$i's/.*/OrganizationID = ABCDE-98765/g' file; done

파이썬

#!/usr/bin/python
import re
j=[]
t=0
h=re.compile(r'OrganizationID.*')
k=open('file','r')
for i in k:
    if re.search(h,i):
        t=t+1
        if (t == 2):
            y=re.sub(h,"OrganizationID = ABCDE-98765",i)
            print y.strip()
        else:
            print i.strip()
    else:
        print i.strip()

산출

oid_section = OIDs

[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn

attributes = v3_req

[OIDs]
OrganizationID = 2.5.4.97        # Don't touch this

[dn]
C = FO
ST = Foobar Monarchy
O = Lorem Ipsum
CN = specific.domain.com
OrganizationID = ABCDE-98765

답변4

이는 Awk를 사용하여 작업을 수행하는 한 가지 방법입니다. REQ_ID를 내장 연관 배열 ENVIRON에서 사용할 수 있는 awk 명령줄 환경에 배치합니다.

$ REQ_ID="ABCDE-98765" \
   awk '
     BEGIN { a[1] = "OrganizationID = " ENVIRON["REQ_ID"] }
     $1 == "[dn]", match($0, /^OrganizationID[[:blank:]]*=/) {
       a[0] = $0
       $0 = a[RSTART]
     }1
  ' ssl.cfg

sed를 사용하려면 REQ_ID가 s/// 명령의 RHS에 배치될 수 있는지 확인해야 하므로 약간의 작업이 더 필요합니다.

$ REQ_ID="ABCDE-98765"; s="[[:blank:]]" 
$ req_id_esc=$(printf '%s\n' "$REQ_ID" | sed -e 's:[\&/]:\\&:g')
$ sed -e "/^[[]dn]/,/^OrganizationID$s*=/s/^\(OrganizationID\)$s*=.*/\1 = ${req_id_esc}/" ssl.cfg
$ REQ_ID="ABCDE-98765" \
   perl -pale '
      s//$1 = $ENV{REQ_ID}/ if 
        $F[0] eq "[dn]" ... /^(OrganizationID)\s*=.*/ and
        defined $1' ssl.cfg

관련 정보