如何匹配IP与带CIDR及注释的列表?ipset/grepcidr问题
Got it, let's tackle this problem. You want to check if an IP belongs to a CIDR range from a list with comments, and get the corresponding comment back—right now ipset test only confirms membership without showing comments, and grepcidr isn't returning the full annotated line. Here are a few solid solutions tailored to different use cases:
1. Bash + grepcidr (Simple for Small Lists)
The issue with your original grepcidr command is that it defaults to outputting only the matching CIDR, not the full line. We can fix this by looping through your list, checking each CIDR with grepcidr, and printing the full line when there's a match:
TARGET_IP="192.168.192.168" # Loop through each line in your CIDR/comment file while read -r cidr comment; do # Use grepcidr's quiet mode to check membership if grepcidr -q "$cidr" <(echo "$TARGET_IP"); then echo "Match found: $cidr $comment" fi done < foo.txt
This works great for smaller lists—no extra dependencies beyond grepcidr, and it's easy to tweak for multiple IPs or different output formats.
2. Leverage ipset + awk (If You're Already Using ipset)
Since you already set up an ipset with comments, we can combine ipset test (to confirm membership) with ipset list (to fetch the comment). The ipset list output formats each entry across two lines (CIDR first, then the comment), so we'll use awk to parse that:
TARGET_IP="192.168.192.168" # First confirm the IP is in the set if ipset test foo "$TARGET_IP" >/dev/null; then # Parse ipset's list output to find the matching CIDR and its comment ipset list foo | awk -v ip="$TARGET_IP" ' # Capture the CIDR from the first line of an entry /^[0-9]/ { current_cidr = $1; next } # Capture the comment from the second line of an entry /comment/ { current_comment = $2; # Verify the CIDR actually contains the IP (extra safety) system("grepcidr -q " current_cidr " <<< " ip) if ($? == 0) { print "Match found: " current_cidr " " current_comment } } ' fi
This is ideal if you're already managing your CIDRs with ipset and don't want to maintain a separate text file.
3. Python Script (Scalable for Large Lists)
For larger lists or more complex logic, Python's built-in ipaddress module is reliable and efficient. No need for external tools, and it handles edge cases (like invalid CIDRs) gracefully:
import ipaddress import sys def find_matching_cidr(target_ip_str, cidr_file): try: target_ip = ipaddress.ip_address(target_ip_str) except ValueError: print(f"Invalid IP address: {target_ip_str}", file=sys.stderr) return with open(cidr_file, "r") as f: for line_num, line in enumerate(f, 1): line = line.strip() if not line: continue # Split line into CIDR and comment (handles comments with spaces) parts = line.split(maxsplit=1) if len(parts) < 2: print(f"Line {line_num}: Missing comment or invalid format", file=sys.stderr) continue cidr_str, comment = parts try: cidr = ipaddress.ip_network(cidr_str, strict=False) if target_ip in cidr: print(f"Match found: {cidr_str} {comment}") except ValueError: print(f"Line {line_num}: Invalid CIDR: {cidr_str}", file=sys.stderr) if __name__ == "__main__": if len(sys.argv) != 3: print(f"Usage: {sys.argv[0]} <target_ip> <cidr_file>", file=sys.stderr) sys.exit(1) find_matching_cidr(sys.argv[1], sys.argv[2])
Run it like this:
python3 match_ip_with_comment.py 192.168.192.168 foo.txt
This method scales well for hundreds/thousands of CIDRs and lets you easily add features like outputting JSON, checking multiple IPs at once, or logging.
内容的提问来源于stack exchange,提问作者Keuvie

