아래와 같이 서버와 도메인 이름이 포함된 파일이 있습니다.
이름.txt:
ABCDomain ContractABCServer_1
ABCDomain ABC_server1
LinkDomain CoreLinkServer_1
TADDomain TADServer_1
(다른 파일에 대해 정렬 및 고유 작업을 수행한 후 위 파일을 얻었습니다.) --- 추가 정보
위 파일에서 값을 추출하여 xyz 명령(서버를 다시 시작하는 데 사용됨)에 다음 형식의 인수로 전달해야 합니다.
산출:
"ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
아래에 설명된 논리를 사용하고 있지만 각 컬렉션의 도메인 이름이 한 번만 나타나야 하므로 원하는 출력이 제공되지 않습니다. 나 역시 같은 선을 유지하는 데 어려움을 겪는다.
- - - - - -시작- - -
DOMAIN=''
IFS=' '
while read line
do
DOMAIN=$(echo "$line" | awk -F " " '{print $1}')
for word in $line
do
if [[ "$word" == "$DOMAIN" ]]; then
Server=$(echo "$line" | awk -F " " '{print $2}' )
echo -n "(server:$ServerName"
fi
done
done < Names.txt
답변1
{
if (dom[$1])
dom[$1]=dom[$1]","$2
else
dom[$1]=$2
}
END {
ORS=",";
for (d in dom)
if (d)
print ("\""d"(server:"dom[d]")""\"")
}
빠르고 더러운 awk 솔루션은 다음과 같습니다. Something.awk로 저장하고 다음을 실행하세요.
awk -f something.awk Names.txt
귀하의 질문에 대한 답변을 위한 빠른 수정논평:
{ dom[$1]=dom[$1] ? dom[$1]",server:"$2 : "server:"$2 }
END {
for (d in dom)
if (d) {
out && out = out","
out = out"\""d"("dom[d]")""\""
}
print out
}
답변2
쉼표로 구분된 문자열을 직접 결합 awk
하고 끝에 조합을 인쇄할 수 있습니다.
$1 == "ABCDomain" {d = (d == "") ? $2 : d "," $2; next}
$1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next}
$1 == "TADDomain" {t = (t == "") ? $2 : t "," $2; next}
END {
printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
}
전임자.
$ awk '
$1 == "ABCDomain" {d = (d == "") ? $2 : d "," $2; next}
$1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next}
$1 == "TADDomain" {t = (t == "") ? $2 : t "," $2; next}
END {
printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
}' Names.txt
"ABCDomain(server:ContractABCServer_1,ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
답변3
이 코드를 사용할 수 있습니다. /tmp
해당 폴더에 디렉터리가 생성된 domains
후 삭제 되므로 실행하기 전에 코드를 읽어 보십시오.
DOMAIN=''
IFS=' '
declare -A domain
mkdir /tmp/domains
while read line
do
DOMAIN=$(echo $line | awk '{print $1}')
SERVER=$(echo $line | awk '{print $2}' )
echo "$SERVER," >> /tmp/domains/$DOMAIN
domain[$DOMAIN]=1
done < Names.txt
sed -ir "$ s/.,$//" /tmp/domains/*
for i in "${!domain[@]}"; do
echo -n "$i(server:";
while read line ; do
echo -n "$line" ;
done < /tmp/domains/$i
echo ")"
done
rm -rf /tmp/domains
그러면 각 도메인 파일 이름에 포함된 서버 목록이 포함되도록 다음 데이터가 포함된 /tmp 폴더에 폴더가 생성됩니다.
$ ls -lhtr /tmp/domains/
total 12K
-rw-rw-r-- 1 arushirai arushirai 11 Jun 19 17:54 TADDomain
-rw-rw-r-- 1 arushirai arushirai 16 Jun 19 17:54 LinkDomain
-rw-rw-r-- 1 arushirai arushirai 32 Jun 19 17:54 ABCDomain
$ cat /tmp/domains/ABCDomain
ContractABCServer_1,
ABC_server
$ cat /tmp/domains/LinkDomain
CoreLinkServer_
$ cat /tmp/domains/TADDomain
TADServer_
답변4
(올바른 출력 형식으로 업데이트됨)
사용 awk
:
BEGIN { OFS = "," }
{ servers[$1] = (servers[$1] == "" ? "server:" $2 : servers[$1] "," "server:" $2 ) }
END {
$0 = ""
for (domain in servers)
$(++n) = sprintf("\"%s(%s)\"", domain, servers[domain])
print
}
그러면 입력 파일을 구문 분석할 때 기본 블록의 특정 도메인에 쉼표로 구분된 문자열로 서버가 추가됩니다. 이는 servers
특정 도메인에 대한 서버를 보유하는 배열을 수정하여 수행됩니다(도메인은 배열의 키입니다).
이 END
블록에서는 배열의 모든 키/필드를 반복하고 servers
지정된 형식으로 출력 레코드를 생성합니다.
제공된 데이터에 대해 실행:
$ awk -f script.awk names.txt
"TADDomain(server:TADServer_1)","ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)"
기본적으로 동등한 bash
스크립트( bash
연관 배열의 경우 4.3+ 필요):
declare -A servers
while read domain server; do
servers[$domain]+="${servers[$domain]:+,}server:$server"
done <names.txt
for domain in "${!servers[@]}"; do
out+="${out:+,}\"$domain(${servers[$domain]})\""
done
printf '%s\n' "$out"
...하지만 "를 참조하세요"쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?".