나는 바꾸고 싶다:
이것:
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" 텍스트를 하드코딩할 수 있습니다.