두 개의 파일이 있습니다.
파일 1:스위치의 인터페이스 수 목록은 다음과 같습니다.
1/1
1/2
1/3
1/4
1/5
.
.
파일 2:VLAN-ID, VLAN-NAME, Interfaces
이 VLAN에 속하는 것을 포함합니다 .
1,"vlan-wifi",1/1,1/7,1/8
2,"vlan-admin",1/3,1/5,1/6
3," " ,3/3,1/3
예를 들어 다음 파일을 사용하여 테이블을 만들려고 합니다.
| interface Switch
VLAN-ID | VLAN-NAME |1/1|1/2|1/3|1/4|1/5|1/6|1/7|1/8|1/9|1/10|...|3/3
1 | vlan-wifi| * | | | | | | * | * | | | |
2 | vlan-admin| | | * | | * | * | | | | | |
3 | | | | * | | | | | | | | | *
이 목표를 어떻게 달성할 수 있나요?
답변1
텍스트를 처리하기 위해 쉘 루프를 사용하고 싶지 않습니다.. 다음은 일반적인 작업입니다 awk
.
awk -F '"? *, *"?' '
!ports_processed {
port[++ports] = $0; width[ports] = length; next
}
FNR==1 {
printf " | interface Switch\nVLAN-ID | VLAN-NAME "
for (i = 1; i <= ports; i++) printf "|%s", port[i]
print ""
}
{
printf "%6d |%11s", $1, $2
split("", member)
for (i = 3; i <= NF; i++) member[$i]
for (i = 1; i <= ports; i++)
printf "| %*s", 1 - width[i], (port[i] in member ? "*" : " ")
print ""
}' file-1 ports_processed=1 file-2
(이는 VLAN 이름에 쉼표, 큰따옴표 또는 개행 문자가 포함되어 있지 않다고 가정합니다(가능한 경우 인코딩 방법을 알아야 합니다).)
다차원 배열을 지원하는 셸에 대한 이 항목의 질문에 답하려면 를 살펴보세요 ksh93
. 또한 csv 구문 분석 및 쓰기 기능도 있습니다.
답변2
필드 너비에 신경쓰지 않으려면 tbl
다음 유틸리티를 사용할 수 있습니다.nroff
perl -F'\"?,\"?' -lane '
BEGIN {
chomp(@A = qx(sort -t/ -k1,1n -k2,2n < $ARGV[0]));
shift;
# prepare table for the tbl utiity
print q/.TS/;
print join(",", qw/allbox center/, qq/tab(\t);/) ;
print join($", qw/c s c/, qw/s/ x $#A) ;
print join($", qw/c r/, qw/c/ x @A), qw/./ ;
print join("\t", $,, q/interface switch/);
print join("\t", qw/VLAN-ID VLAN-NAME/, @A);
}
print
join("\t", @F[0,1], map { my $e = $_; (0 < grep { $e eq $_ } @F[2..$#F]) ? q[*] : q[] } @A);
END { print q/.TE/; }
' file-1 file-2 | tbl - | nroff -Tascii -ms | sed -n '/./!d;$!N;s/.*\n.\(.*\)./\1/p'
결과:
| interface switch
VLAN-ID | VLAN-NAME | 1/1 | 1/2 | 1/3 | 1/4 | 1/5 | 1/6 | 1/7 | 1/8 | 1/9 | 1/10 | 3/3
1 | vlan-wifi | * | | | | | | * | * | | |
2 | vlan-admin | | | * | | * | * | | | | |
3 | | | | * | | | | | | | | *
답변3
Python을 사용하여 이를 수행하는 한 가지 방법은 다음과 같습니다. 알아채다파일 1귀하의 질문에 따르면 필요하지 않은 것 같으므로 이 스크립트는 하나의 매개변수만 사용합니다.
암호:
import sys
filename = sys.argv[1]
vids = {}
intfs = set()
with open(filename, 'rU') as f:
for line in f:
vid, vname, vintf = line.strip().split(',', 2)
vintf = vintf.split(',')
vids[int(vid)] = (vname.strip('"').strip(), vintf)
intfs |= set(vintf)
intfs = [(i, len(i)) for i in
sorted(intfs, key=lambda x: tuple(int(y) for y in x.split('/')))]
max_name_len = max(len(i[0]) for i in vids.values()) + 1
line = ('VLAN-ID |%%%ds' % max_name_len) % (
'VLAN-NAME' + ' ' * ((max_name_len - 9) / 2))
for intf, width in intfs:
line += ('|%%%ds' % width) % intf
print(line)
fmt = '%%5s |%%%ds' % max_name_len
for vid, values in sorted(vids.items()):
vname, have_intfs = values
line = fmt % (vid, vname)
for intf, width in intfs:
line += ('| %%-%ds' % (width-1)) % (
'*' if intf in have_intfs else '')
print(line)
결과:
VLAN-ID | VLAN-NAME |1/1|1/3|1/5|1/6|1/7|1/8|1/10|3/3
1 | vlan-wifi| * | | | | * | * | |
2 | vlan-admin| | * | * | * | | | |
3 | | | * | | | | | * | *
답변4
다음과 같은 배열을 사용하여 이 작업을 수행 할 수 있습니다 bash
.
#!/bin/bash
# store the numerically sorted file1 into array A
A=( $(sort -t/ -k1,1n -k2,2n < file-1) )
# determine the maximum field width by examining the lengths of the 2nd field
# and the string "VLAN-NAME" coming for the header.
maxW=$(
{ echo ',"VLAN-NAME"'; cat < file-2; } |
cut -d, -f2 | awk '{print length-2}' |
sort -nr | sed q
)
# first two fields of the header
B=( "VLAN-ID " "$(printf " %-${maxW}s\n" "VLAN-NAME")" )
# complete header: from array B and the numerically sorted file1 contents
C=( "${B[@]}" "$(IFS="|"; echo "${A[*]}")" )
# display the header
echo "$(IFS="|"; echo "${B[*]}")" |\
sed -e 's/[^[:blank:]]/ /g;s/$/| interface switch/'
echo "$(IFS="|"; echo "${C[*]}")"
# remaining lines printed
while IFS=, read -ra B; do
D=(x)
for arg in "${A[@]}"; do
case " ${B[*]:2} " in *" $arg "* ) res=* ;; * ) res=\ ;; esac
var1=${arg//[!\/]/ } D=( "${D[@]}" "${var1/\//$res}" )
done
printf "%8s| %${maxW}s|%s\n" "${B[0]}" "${B[1]//\"/}" "$(IFS="|";echo "${D[*]:1}")"
done < file-2
결과
| interface switch
VLAN-ID | VLAN-NAME |1/1|1/2|1/3|1/4|1/5|1/6|1/7|1/8|1/9|1/10|3/3
1| vlan-wifi| * | | | | | | * | * | | |
2| vlan-admin| | | * | | * | * | | | | |
3| | | | * | | | | | | | | *