如何对齐子网IP与主机状态位?实现状态位居中显示
解决IP与对应状态位的对齐问题
没问题,咱们来搞定这个IP和状态位对齐的需求。你想要的是让每个在线/离线标记(0或1)正好对应在上方IP的中心位置,同时兼容不同长度的IP地址,核心是用固定宽度的格式化输出来替代原脚本里的制表符——毕竟制表符没法根据IP长度自适应对齐,肯定达不到你要的居中效果。
核心思路
- 先获取子网内所有IP,计算出最长IP的长度,以此为基础设置每个IP字段的固定宽度(额外加2个字符的边距,让排版更宽松美观)。
- 用
printf格式化输出IP行,确保每个IP都占满固定宽度的字段。 - 对每个状态位(0/1),计算其在对应字段的中心位置,通过填充前后空格让状态位精准居中显示。
修正后的完整脚本
我已经修复了原脚本里的子网计算笔误(把ii4改成了正确的i4),并加入了对齐逻辑:
#!/bin/bash # written by Cosimo Colaci # 修正:添加IP与状态对齐逻辑,修复子网计算笔误 # Declarations ROOT_UID=0 E_NOROOT=65 declare -a iplist echo "Reading hosts status..." # Must run as root. # if [ "$UID" -ne "$ROOT_UID" ] # then # echo "You need to run this script as root. Exiting..." # exit $E_NOROOT # fi # Find Gateway IP and Netmask ip_gateway=$(route | tail -1 | awk '{print $1}') netmask=$(route | tail -1 | awk '{print $3}') # echo "$netmask" FOR DEBUG # Find subnet OLDIFS="$IFS" IFS=. read -r i1 i2 i3 i4 <<< "$ip_gateway" read -r m1 m2 m3 m4 <<< "$netmask" # 修正笔误:ii4 改为 i4 subnet_ip=$(printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))") # echo "$subnet_ip" FOR DEBUG IFS="$OLDIFS" # Express netmask in CIDR notation, to know how many hosts to scan cidr_by_netmask() { #function returns prefix for given netmask in arg1 bits=0 for octet in $(echo $1| sed 's/\./ /g'); do binbits=$(echo "obase=2; ibase=10; ${octet}"| bc | sed 's/0//g') let bits+=${#binbits} done echo "/${bits}" } suffix=$(cidr_by_netmask $netmask) # echo "$suffix" FOR DEBUG # First row of matrix file: all IPs in subnet iplist=( $(nmap -sL $subnet_ip$suffix | grep "Nmap scan report" | awk '{print $NF}') ) # echo "${iplist[@]}" FOR DEBUG # 计算最长IP的长度,作为字段宽度(加2留边距) max_ip_len=0 for ip in "${iplist[@]}"; do ip_len=${#ip} if (( ip_len > max_ip_len )); then max_ip_len=$ip_len fi done field_width=$(( max_ip_len + 2 )) # 输出第一行(IP行) printf "%-${field_width}s " "#IP/TIME" for ip in "${iplist[@]}"; do printf "%-${field_width}s " "$ip" done echo "" > ip-time_matrix.txt # Other rows echo "Scanning hosts every 10s..." echo "Hit CTRL-C to stop and check file \"ip-time_matrix.txt\"" while true; do nmap -sP $subnet_ip$suffix &>temp_esame95a.txt # 输出时间列 printf "%-${field_width}s " "$(date +%T)" for ip in "${iplist[@]}"; do if grep "$ip" temp_esame95a.txt &>/dev/null; then status=1 else status=0 fi # 计算状态位的前后空格,让其居中 leading_spaces=$(( (field_width - 1) / 2 )) trailing_spaces=$(( field_width - leading_spaces - 1 )) printf "%*s%d%*s " $leading_spaces "" $status $trailing_spaces "" done echo "" >> ip-time_matrix.txt sleep 10 done
效果说明
- 不管IP是短的
71.5.0.0还是长的192.168.100.255,每个IP都会占据相同宽度的字段,排版整齐。 - 每个状态位(0或1)会精准落在对应IP字段的中心位置,完全符合你的需求。
- 修复了原脚本中计算子网IP时的笔误,避免脚本执行失败。
内容的提问来源于stack exchange,提问作者Alex_DeLarge
相关产品推荐
相关产品推荐

