如何用Python转换Linux静态路由配置文件格式?求推荐相关库
Hey there! You don't need any special third-party libraries for this task—Python's standard library has everything you need to handle text parsing, file I/O, and subnet mask conversion. Let's walk through a complete solution that builds on the code snippet you started with.
Step 1: Subnet Mask to Prefix Length Conversion
First, we need a helper function to convert subnet masks (like 255.255.255.0) to CIDR prefix lengths (like 24). Here's a straightforward implementation:
def mask_to_prefix(mask): # Split mask into octets, convert to binary, count total 1 bits octets = list(map(int, mask.split('.'))) binary_mask = ''.join(f'{octet:08b}' for octet in octets) return str(binary_mask.count('1'))
Step 2: Parse and Convert Route Files
Next, we'll write logic to read each route-interface file, group the ADDRESSx, NETMASKx, GATEWAYx entries by their numeric suffix, and convert each group to the CIDR format.
Here's the full code that integrates with your initial glob setup:
import glob import re def mask_to_prefix(mask): try: octets = list(map(int, mask.split('.'))) if len(octets) != 4 or any(o < 0 or o > 255 for o in octets): raise ValueError("Invalid subnet mask") binary_mask = ''.join(f'{octet:08b}' for octet in octets) return str(binary_mask.count('1')) except Exception as e: print(f"Error processing mask {mask}: {e}") return None def convert_route_file(file_path): routes = {} # Read all lines from the file with open(file_path, 'r') as f: for line in f: line = line.strip() if not line or '=' not in line: continue # Match keys like ADDRESS0, NETMASK1, GATEWAY2 match = re.match(r'(ADDRESS|NETMASK|GATEWAY)(\d+)=(.+)', line) if not match: continue key_type, idx, value = match.groups() idx = int(idx) # Initialize entry if not exists if idx not in routes: routes[idx] = {'address': None, 'mask': None, 'gateway': None} # Populate the entry if key_type == 'ADDRESS': routes[idx]['address'] = value elif key_type == 'NETMASK': routes[idx]['mask'] = value elif key_type == 'GATEWAY': routes[idx]['gateway'] = value # Generate converted routes converted = [] for idx in sorted(routes.keys()): entry = routes[idx] if not all([entry['address'], entry['mask'], entry['gateway']]): print(f"Skipping incomplete route {idx} in {file_path}") continue prefix = mask_to_prefix(entry['mask']) if not prefix: print(f"Skipping route {idx} due to invalid mask in {file_path}") continue converted_line = f"{entry['address']}/{prefix} via {entry['gateway']}" converted.append(converted_line) return converted # Process all route-* files in the target directory if __name__ == "__main__": # Replace with your target path (e.g., '/etc/sysconfig/network-scripts/route-*') route_files = glob.glob('./route-*') for file in route_files: print(f"Processing {file}...") converted_routes = convert_route_file(file) if converted_routes: print("Converted routes:") for route in converted_routes: print(f" {route}") else: print(" No valid routes found or converted.")
How This Works
- Mask Conversion: The
mask_to_prefixfunction converts a dotted-decimal subnet mask to a CIDR prefix by counting the number of1bits in its binary representation. - File Parsing: We use regex to extract the numeric index from each route entry key, then group entries by this index to ensure we match the correct address, mask, and gateway for each route.
- Error Handling: The code checks for incomplete entries (missing address/mask/gateway) and invalid subnet masks, skipping them with a warning instead of crashing.
- Batch Processing: Using
glob, we can process allroute-*files in a directory, which aligns with your initial code snippet.
Example Output
If your input file has:
ADDRESS0=192.168.1.0 NETMASK0=255.255.255.0 GATEWAY0=10.0.0.1 ADDRESS1=10.1.0.0 NETMASK1=255.255.0.0 GATEWAY1=10.0.0.2
The converted output will be:
192.168.1.0/24 via 10.0.0.1 10.1.0.0/16 via 10.0.0.2
内容的提问来源于stack exchange,提问作者Ibrahim Quraish

