You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对齐子网IP与主机状态位?实现状态位居中显示

解决IP与对应状态位的对齐问题

没问题,咱们来搞定这个IP和状态位对齐的需求。你想要的是让每个在线/离线标记(0或1)正好对应在上方IP的中心位置,同时兼容不同长度的IP地址,核心是用固定宽度的格式化输出来替代原脚本里的制表符——毕竟制表符没法根据IP长度自适应对齐,肯定达不到你要的居中效果。

核心思路

  1. 先获取子网内所有IP,计算出最长IP的长度,以此为基础设置每个IP字段的固定宽度(额外加2个字符的边距,让排版更宽松美观)。
  2. 用printf格式化输出IP行,确保每个IP都占满固定宽度的字段。
  3. 对每个状态位(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:08:32