다음 형식의 출력 파일("inventory.list")에 문제가 있습니다.
hostname1.env1.domain | abc | environment1
hostname2.env1.domain | abc | environment1
hostname3.env2.domain | abc | environment2
hostname4.env2.domain | abc | environment2
hostname5.env1.domain | def | environment1
hostname6.env2.domain | def | environment2
(6 rows)
다른 형식으로 다른 파일에 씁니다.
[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain
[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain
[def.environment1]
hostname5.env1.domain
[def.environment2]
hostname6.env2.domain
abc
역할은 서버에 할당 되며 def
각 역할은 여러 서버를 가질 수 있을 뿐만 아니라 이름은 같지만 환경이 다른 역할을 가질 수 있습니다. 각 호스트 이름을 고유한 [role.environment] 그룹으로 나누고 추가적으로 행 개수인 파일의 마지막 줄을 완전히 제거해야 했습니다(파일은 SQL 쿼리의 출력임).
파일을 읽고, 파이프와 공백을 제거하고, 역할/환경 그룹을 할당/출력할 수 있습니다. 문제 없습니다.
#! /bin/bash
while IFS='| ' read -r certname role env; do
printf '%s\n' "[""$role"".""$env""]"
done < "/tmp/inventory.list"
...역할/환경 그룹 이름을 깔끔하게 제공합니다.
[abc.environment1]
[abc.environment2]
[def.environment1]
[def.environment2]
그러나 각 그룹 이름 아래의 각 역할/환경 그룹에 연결된 호스트 이름을 인쇄하는 방법을 알 수 없으며 내 스크립트가 마지막 줄 수 줄을 무시하도록 만드는 방법도 알 수 없습니다. 내 역할과 환경 필드(두 번째 및 세 번째 필드)를 자체 배열에 추가로 할당한 다음 이를 참조하여 각 고유 그룹에 연결된 호스트 이름을 가져와야 하지만 지금은 어떻게 해야 할지 모르겠습니다. . 누구든지 조언을 해줄 수 있나요?
답변1
텍스트 유틸리티를 사용하여 텍스트를 처리하겠습니다.쉘 루프를 사용하여 텍스트를 처리하는 대신(여기서는 IFS=' |'
귀하의 경우에는 잘 작동합니다). 좋다:
awk -F ' *[|] *' '
NF == 3 {host[$2"."$3] = host[$2"."$3] $1 "\n"}
END{for (i in host) print "[" i "]\n" host[i]}' < file
출품 순서는 보장되지 않습니다. GNU를 사용하여 키 기반 정렬을 awk
추가합니다 .BEGIN{PROCINFO["sorted_in"] = "@ind_str_asc"}
사용 중인 RDBMS에 따라 올바른 형식으로 표시되도록 할 수도 있습니다(예:GROUP_CONCAT
존재하다mysql
또는string_agg
포스트그레스에서).
먼저, RDBMS 쿼리 유틸리티에 출력을 후처리에 더 적합한 형식으로 지정하도록 요청할 수도 있습니다(예: 머리글, 바닥글 제거, 탭으로 구분된 값 사용).
답변2
연관 배열을 사용하여 각 역할 및 환경에 대한 인증서 이름을 저장합니다.
#! /bin/bash
unset -v envs
declare -A envs
while IFS='| ' read -r certname role env; do
envs["$role.$env"]+="$certname"$'\n'
done < /tmp/inventory.list
for e in "${!envs[@]}" ; do
printf '%s\n' "[$e]" "${envs[$e]}"
done
이러한 부분을 정렬하려면 키를 인쇄하고 정렬한 다음 다시 읽고 관련 값을 출력하면 됩니다.
for e in "${!envs[@]}" ; do
printf '%s\n' "$e"
done | sort | while read -r e ; do
printf '%s\n' "[$e]" "${envs[$e]}"
done
답변3
펄 매직:
$ perl -lne '@F=split(/\s*\|\s*/); push @{$k{"$F[1].$F[2]"}},$F[0];
END{foreach (keys(%k)){print "[$_]"; print join "\n",@{$k{$_}}} }' file
[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain
[def.environment1]
hostname5.env1.domain
[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain
[def.environment2]
hostname6.env2.domain
답변4
awk를 사용하는 한 가지 방법:
$ sed 's/ //g' file | awk -F"|" '{x="["$2"."$3"]";}!(x in a){print x;a[x];}{print $1}'