Bash - 파일 구성 형식 변경

Bash - 파일 구성 형식 변경

나는 바꾸고 싶다:

이것:

client 192.168.100.1 {
    secret = ThisIStheSECRET
    shortname = HOSTNAME
}
client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}

저것:

client HOSTNAME { secret = ThisIStheSECRET, ipaddr = 192.168.100.1 }
client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }

어떻게 해야 하나요? 어떤 도구를 사용해야 합니까?

답변1

간단한 awk스크립트:

awk '
    /^client/               { ipaddr    = $2                              }
    /^[[:blank:]]*shortname/{ shortname = $3                              }
    /^[[:blank:]]*secret/   { secret    = $0; sub("^[^=]*= ", "", secret) }
    /^}/ {
        printf("client %s { secret = %s, ipaddr = %s }\n",
            shortname, secret, ipaddr);
    }' file

입력 파일에서 필요한 정보를 찾으면 간단히 구문 분석하고 }줄 시작 부분에서 를 누르면 수집된 정보를 올바른 형식으로 출력합니다.

텍스트 구문 분석은 텍스트에 secret다음 내용이 포함될 것으로 예상하기 때문에 특별합니다.아무것, 심지어 필드 구분 기호. 먼저 변수를 secret전체 줄로 설정한 다음 첫 번째 공백 앞의 모든 항목 =과 그 뒤의 단일 공백을 제거합니다.

주어진 파일

client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}
client 10.0.0.1 {
    secret =     This is it, the secret!, ipaddr = 10.0.0.1
    shortname = myhost.local
}

(비밀번호 시작 부분에 공백 4개가 있음을 참고하세요.) 이렇게 하면 다음과 같은 결과가 나옵니다.

client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }
client myhost.local { secret =     This is it, the secret!, ipaddr = 10.0.0.1, ipaddr = 10.0.0.1 }

답변2

나는 다음과 같은 일을 할 것입니다 :

perl -0777 -pe 's{client\s+(\S+)\s*\{\s*(secret = .*)\s+shortname\s*=\s*(.*)\s*\}}
                 {client $3 { $2, ipaddr = $1 }}g'

답변3

내가 바라던 것만큼 "간단"하지는 않지만 이렇게 하면 문제가 해결될 것입니다.

perl -pe 's/(\w)\s*$/\1,\n/;' your_filename | perl -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;'

영숫자(A ~ Z, a ~ z, 0 ~ 9 및 _)로 끝나는 줄에 쉼표를 추가하는 정규식을 실행합니다.

줄이 }(음수 뒤보기 활용)로 끝나지 않는 한 줄 바꿈 (및 그 주변의 공백)을 공백으로 바꾸는 또 다른 정규식을 실행 한 다음 마지막으로 최종 형식 지정을위한 정규식을 실행합니다 (호스트 이름과 IP를 전환하고 관련없는 내용 삭제) 쉼표 )

이는 개행을 무시하고 결과를 새 파일(또는 기존 파일)로 리디렉션하고 > your_new_filename끝에 추가할 수 있습니다. 이렇게 하면 이 솔루션은 플래그를 사용하여 -i파일을 수정할 수 있습니다.

perl -i -pe 's/(\w)\s*$/\1,\n/;' your_filename
perl -i -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;' your_filename

답변4

이 문제를 해결하는 더 좋은 방법이 있다고 확신하지만 다음 조합으로 해결 sed했습니다 awk.

sed ':a;N;$!ba;s/\n/ /g' file | sed -e 's/    //g' -e 's/ client/\nclient/' | awk '{print $1" "$9" "$3" "$4" "$5" "$6",  ipaddress "$8" "$2" "$10}'

설명하다

  • sed ':a;N;$!ba;s/\n/ /g'모든 새 줄을 공백으로 바꿉니다. 이것을 참조하세요이 답변더 많은 정보를 알고 싶다면
  • sed -e 's/ //g'4개의 스페이서 블록을 하나의 공간으로 교체합니다.
  • -e 's/ client/\nclient/'클라이언트 문자열이 일치하면 새 줄을 추가합니다.
  • awk '{print $1" "$9" "$3" "$4" "$5" "$6", ipaddress "$8" "$2" "$10}'기본적으로 awk는 텍스트를 공백으로 구분하므로 여기서는 호스트 이름 변수($9)와 IP 주소 변수($2)를 원하는 순서대로 인쇄하면 됩니다. "shortname" 변수($7)를 무시하고 ",ipaddress" 텍스트를 하드코딩할 수 있습니다.

관련 정보