
Regular Expression in Java – Regex Example Tutorial
If you’ve ever found yourself parsing server logs, extracting configuration data from files, or automating text processing tasks on your Linux boxes, you know how crucial it is to have powerful pattern matching at your fingertips. Regular expressions in Java are your secret weapon for handling complex string operations efficiently. Whether you’re managing server configurations, processing log files, or building monitoring scripts, mastering regex will save you countless hours and make your automation workflows bulletproof. This comprehensive guide will walk you through everything from basic pattern matching to advanced regex techniques that’ll transform how you handle text processing in your server environment.
How Does Java Regex Work?
Java’s regex engine operates on a finite state automaton model, which means it processes patterns character by character through your input strings. The magic happens in the java.util.regex
package, which provides three main classes that work together like a well-oiled machine:
- Pattern – Compiles and stores your regex pattern
- Matcher – Performs the actual matching operations
- PatternSyntaxException – Handles errors when your regex goes sideways
The process is straightforward: compile your pattern once, create a matcher for your input text, then unleash various matching methods. This approach is particularly efficient when you’re processing large log files or batch operations on your servers.
import java.util.regex.*;
// Basic pattern compilation and matching
Pattern pattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
Matcher matcher = pattern.matcher("Server IP: 192.168.1.100");
boolean found = matcher.find();
Under the hood, Java’s regex engine uses a backtracking algorithm that tries different paths through your pattern until it finds a match or exhausts all possibilities. This is why poorly written regex patterns can sometimes bring your server to its knees – always test your patterns with representative data!
Step-by-Step Setup and Implementation
Getting started with Java regex doesn’t require any external dependencies – it’s baked right into the JDK. Here’s how to set up your development environment and start crafting regex patterns:
Environment Setup
# Verify Java installation
java -version
# Create a new directory for your regex experiments
mkdir regex-tutorial && cd regex-tutorial
# Create your first regex test file
cat > RegexTest.java << 'EOF'
import java.util.regex.*;
public class RegexTest {
public static void main(String[] args) {
System.out.println("Java Regex Engine Ready!");
}
}
EOF
# Compile and run
javac RegexTest.java
java RegexTest
Basic Pattern Creation
Start with these fundamental patterns that you’ll use constantly in server management:
import java.util.regex.*;
public class BasicPatterns {
public static void main(String[] args) {
// IP address validation
String ipPattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
Pattern ip = Pattern.compile(ipPattern);
// Test cases
String[] testIPs = {"192.168.1.1", "256.1.1.1", "10.0.0.1"};
for (String testIP : testIPs) {
Matcher matcher = ip.matcher(testIP);
System.out.println(testIP + " is valid: " + matcher.matches());
}
// Email pattern
String emailPattern = "^[A-Za-z0-9+_.-]+@([A-Za-z0-9.-]+\\.[A-Za-z]{2,})$";
Pattern email = Pattern.compile(emailPattern);
// URL pattern for log parsing
String urlPattern = "https?://[\\w\\.-]+(?:\\.[a-zA-Z]{2,})+(?:/[\\w\\.-]*)*/?";
Pattern url = Pattern.compile(urlPattern);
}
}
Advanced Matching Techniques
import java.util.regex.*;
import java.util.*;
public class AdvancedMatching {
public static void main(String[] args) {
// Log parsing example
String logLine = "2023-10-15 14:30:25 [ERROR] 192.168.1.50 - Failed login attempt from user: admin";
// Named groups for better readability
String logPattern = "(?\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})\\s+" +
"\\[(?\\w+)\\]\\s+" +
"(?\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\s+-\\s+" +
"(?.+)";
Pattern logPat = Pattern.compile(logPattern);
Matcher logMatcher = logPat.matcher(logLine);
if (logMatcher.find()) {
System.out.println("Timestamp: " + logMatcher.group("timestamp"));
System.out.println("Level: " + logMatcher.group("level"));
System.out.println("IP: " + logMatcher.group("ip"));
System.out.println("Message: " + logMatcher.group("message"));
}
// Find all matches
String text = "Contact us at admin@server1.com or support@server2.com";
String emailRegex = "[\\w\\.-]+@[\\w\\.-]+\\.[a-zA-Z]{2,}";
Pattern emailPattern = Pattern.compile(emailRegex);
Matcher emailMatcher = emailPattern.matcher(text);
List emails = new ArrayList<>();
while (emailMatcher.find()) {
emails.add(emailMatcher.group());
}
System.out.println("Found emails: " + emails);
}
}
Real-World Examples and Use Cases
Server Log Analysis
One of the most common scenarios you’ll encounter is parsing Apache or Nginx access logs. Here’s a robust solution that handles various log formats:
import java.util.regex.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class LogAnalyzer {
// Apache Common Log Format
private static final String APACHE_LOG_PATTERN =
"^(\\S+)\\s+\\S+\\s+\\S+\\s+\\[(.*?)\\]\\s+\"(\\w+)\\s+(\\S+)\\s+(\\S+)\"\\s+(\\d{3})\\s+(\\d+|-)";
// Nginx combined log format
private static final String NGINX_LOG_PATTERN =
"^(\\S+)\\s+-\\s+-\\s+\\[(.*?)\\]\\s+\"(\\w+)\\s+(\\S+)\\s+(\\S+)\"\\s+(\\d{3})\\s+(\\d+)\\s+\"(.*?)\"\\s+\"(.*?)\"";
public static void analyzeApacheLogs(String logFile) throws IOException {
Pattern pattern = Pattern.compile(APACHE_LOG_PATTERN);
Map<String, Integer> ipCounts = new HashMap<>();
Map<Integer, Integer> statusCounts = new HashMap<>();
Files.lines(Paths.get(logFile)).forEach(line -> {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String ip = matcher.group(1);
int status = Integer.parseInt(matcher.group(6));
ipCounts.merge(ip, 1, Integer::sum);
statusCounts.merge(status, 1, Integer::sum);
}
});
// Top 10 IPs
System.out.println("Top 10 IP addresses:");
ipCounts.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(10)
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
// Status code distribution
System.out.println("\nStatus Code Distribution:");
statusCounts.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
}
public static void main(String[] args) {
try {
analyzeApacheLogs("/var/log/apache2/access.log");
} catch (IOException e) {
System.err.println("Error reading log file: " + e.getMessage());
}
}
}
Configuration File Validation
When managing servers, you often need to validate configuration files. Here’s a comprehensive example for parsing and validating different config formats:
import java.util.regex.*;
import java.io.*;
import java.util.*;
public class ConfigValidator {
// Common configuration patterns
private static final Map<String, Pattern> CONFIG_PATTERNS = new HashMap<>();
static {
// Key-value pairs (key=value or key: value)
CONFIG_PATTERNS.put("KEY_VALUE", Pattern.compile("^\\s*([\\w\\.]+)\\s*[=:]\\s*(.+)$"));
// Section headers [section_name]
CONFIG_PATTERNS.put("SECTION", Pattern.compile("^\\s*\\[([\\w\\s]+)\\]\\s*$"));
// Comments (# or // or ;)
CONFIG_PATTERNS.put("COMMENT", Pattern.compile("^\\s*[#;/].*$"));
// Empty lines
CONFIG_PATTERNS.put("EMPTY", Pattern.compile("^\\s*$"));
// Port numbers
CONFIG_PATTERNS.put("PORT", Pattern.compile("^(6553[0-5]|655[0-2]\\d|65[0-4]\\d{2}|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3})$"));
// Domain names
CONFIG_PATTERNS.put("DOMAIN", Pattern.compile("^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$"));
}
public static class ConfigValidationResult {
public boolean isValid;
public List errors;
public Map<String, String> config;
public ConfigValidationResult() {
this.errors = new ArrayList<>();
this.config = new HashMap<>();
}
}
public static ConfigValidationResult validateConfig(String configFile) throws IOException {
ConfigValidationResult result = new ConfigValidationResult();
result.isValid = true;
List lines = Files.readAllLines(Paths.get(configFile));
int lineNumber = 0;
for (String line : lines) {
lineNumber++;
// Skip comments and empty lines
if (CONFIG_PATTERNS.get("COMMENT").matcher(line).matches() ||
CONFIG_PATTERNS.get("EMPTY").matcher(line).matches()) {
continue;
}
// Process sections
Matcher sectionMatcher = CONFIG_PATTERNS.get("SECTION").matcher(line);
if (sectionMatcher.matches()) {
System.out.println("Found section: " + sectionMatcher.group(1));
continue;
}
// Process key-value pairs
Matcher kvMatcher = CONFIG_PATTERNS.get("KEY_VALUE").matcher(line);
if (kvMatcher.matches()) {
String key = kvMatcher.group(1);
String value = kvMatcher.group(2);
// Validate specific keys
if (key.toLowerCase().contains("port")) {
if (!CONFIG_PATTERNS.get("PORT").matcher(value).matches()) {
result.errors.add("Line " + lineNumber + ": Invalid port number '" + value + "'");
result.isValid = false;
}
}
if (key.toLowerCase().contains("domain") || key.toLowerCase().contains("host")) {
if (!CONFIG_PATTERNS.get("DOMAIN").matcher(value).matches()) {
result.errors.add("Line " + lineNumber + ": Invalid domain name '" + value + "'");
result.isValid = false;
}
}
result.config.put(key, value);
} else {
result.errors.add("Line " + lineNumber + ": Unrecognized format '" + line + "'");
result.isValid = false;
}
}
return result;
}
public static void main(String[] args) {
try {
ConfigValidationResult result = validateConfig("server.conf");
if (result.isValid) {
System.out.println("Configuration is valid!");
System.out.println("Loaded " + result.config.size() + " configuration items");
} else {
System.out.println("Configuration has errors:");
result.errors.forEach(System.out::println);
}
} catch (IOException e) {
System.err.println("Error reading configuration file: " + e.getMessage());
}
}
}
Performance Comparison Table
Operation | Java Regex | String methods | Manual parsing | Best Use Case |
---|---|---|---|---|
Simple substring search | ~500ms/10K records | ~50ms/10K records | ~30ms/10K records | Use String.contains() |
Pattern matching | ~800ms/10K records | Not applicable | ~2000ms/10K records | Use Regex |
Complex validation | ~1200ms/10K records | Not applicable | ~5000ms/10K records | Use Regex |
Log parsing | ~1500ms/10K records | ~3000ms/10K records | ~2500ms/10K records | Use Regex with compilation caching |
Positive and Negative Test Cases
Here’s a comprehensive testing framework that covers both successful matches and edge cases that could break your patterns:
import java.util.regex.*;
import java.util.*;
public class RegexTestSuite {
public static class TestCase {
String input;
boolean expectedMatch;
String description;
public TestCase(String input, boolean expectedMatch, String description) {
this.input = input;
this.expectedMatch = expectedMatch;
this.description = description;
}
}
public static void runTestSuite(String patternStr, List testCases) {
Pattern pattern = Pattern.compile(patternStr);
int passed = 0;
int failed = 0;
System.out.println("Testing pattern: " + patternStr);
System.out.println("=" + "=".repeat(50));
for (TestCase testCase : testCases) {
Matcher matcher = pattern.matcher(testCase.input);
boolean actualMatch = matcher.matches();
if (actualMatch == testCase.expectedMatch) {
System.out.println("✓ PASS: " + testCase.description);
passed++;
} else {
System.out.println("✗ FAIL: " + testCase.description);
System.out.println(" Input: '" + testCase.input + "'");
System.out.println(" Expected: " + testCase.expectedMatch + ", Got: " + actualMatch);
failed++;
}
}
System.out.println("\nResults: " + passed + " passed, " + failed + " failed");
System.out.println("Success rate: " + (100.0 * passed / (passed + failed)) + "%\n");
}
public static void main(String[] args) {
// Test IP address validation
List ipTests = Arrays.asList(
// Positive cases
new TestCase("192.168.1.1", true, "Valid private IP"),
new TestCase("10.0.0.1", true, "Valid private IP (10.x)"),
new TestCase("172.16.0.1", true, "Valid private IP (172.x)"),
new TestCase("8.8.8.8", true, "Valid public IP"),
new TestCase("127.0.0.1", true, "Localhost"),
new TestCase("0.0.0.0", true, "All zeros"),
new TestCase("255.255.255.255", true, "All max values"),
// Negative cases
new TestCase("256.1.1.1", false, "First octet too high"),
new TestCase("1.256.1.1", false, "Second octet too high"),
new TestCase("1.1.256.1", false, "Third octet too high"),
new TestCase("1.1.1.256", false, "Fourth octet too high"),
new TestCase("192.168.1", false, "Missing octet"),
new TestCase("192.168.1.1.1", false, "Extra octet"),
new TestCase("192.168.01.1", false, "Leading zero"),
new TestCase("192.168.-1.1", false, "Negative number"),
new TestCase("192.168.1.", false, "Trailing dot"),
new TestCase(".192.168.1.1", false, "Leading dot"),
new TestCase("192.168.1.1/24", false, "With CIDR notation"),
new TestCase("192.168.1.a", false, "Non-numeric character"),
new TestCase("", false, "Empty string"),
new TestCase("192.168.1.1 ", false, "Trailing space"),
new TestCase(" 192.168.1.1", false, "Leading space")
);
String ipPattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
runTestSuite(ipPattern, ipTests);
// Test email validation
List emailTests = Arrays.asList(
// Positive cases
new TestCase("user@example.com", true, "Standard email"),
new TestCase("admin@server.co.uk", true, "Multiple domain levels"),
new TestCase("user.name@example.com", true, "Dot in username"),
new TestCase("user+tag@example.com", true, "Plus in username"),
new TestCase("user_name@example.com", true, "Underscore in username"),
new TestCase("123@example.com", true, "Numeric username"),
// Negative cases
new TestCase("user@", false, "Missing domain"),
new TestCase("@example.com", false, "Missing username"),
new TestCase("user..name@example.com", false, "Double dot in username"),
new TestCase("user@example", false, "Missing TLD"),
new TestCase("user@.example.com", false, "Domain starts with dot"),
new TestCase("user@example..com", false, "Double dot in domain"),
new TestCase("user name@example.com", false, "Space in username"),
new TestCase("user@exam ple.com", false, "Space in domain"),
new TestCase("", false, "Empty string")
);
String emailPattern = "^[A-Za-z0-9+_.-]+@([A-Za-z0-9.-]+\\.[A-Za-z]{2,})$";
runTestSuite(emailPattern, emailTests);
}
}
Integration with Server Management Tools
Java regex becomes incredibly powerful when integrated with server automation tools. Here are some practical integrations:
Shell Script Integration
#!/bin/bash
# Script to validate server configurations using Java regex
JAVA_VALIDATOR="ConfigValidator"
CONFIG_FILE="/etc/myapp/server.conf"
LOG_FILE="/var/log/config-validation.log"
# Compile Java validator if needed
if [ ! -f "${JAVA_VALIDATOR}.class" ]; then
javac ${JAVA_VALIDATOR}.java
fi
# Run validation
echo "$(date): Starting configuration validation" >> $LOG_FILE
java $JAVA_VALIDATOR $CONFIG_FILE >> $LOG_FILE 2>&1
if [ $? -eq 0 ]; then
echo "$(date): Configuration validation successful" >> $LOG_FILE
systemctl restart myapp
else
echo "$(date): Configuration validation failed - service not restarted" >> $LOG_FILE
exit 1
fi
Cron Job for Log Analysis
# Add to crontab (crontab -e)
# Run log analysis every hour
0 * * * * /usr/local/bin/java -cp /opt/monitoring LogAnalyzer /var/log/apache2/access.log > /var/log/hourly-stats.log 2>&1
# Daily log rotation and analysis
0 0 * * * /usr/local/bin/rotate-and-analyze-logs.sh
Integration with Monitoring Systems
Here’s how you can integrate regex-based log analysis with popular monitoring solutions:
import java.util.regex.*;
import java.util.*;
import java.time.*;
import java.io.*;
public class MonitoringIntegration {
// Patterns for different types of alerts
private static final Pattern ERROR_PATTERN = Pattern.compile(".*\\[ERROR\\].*");
private static final Pattern CRITICAL_PATTERN = Pattern.compile(".*\\[CRITICAL\\].*|.*FATAL.*");
private static final Pattern FAILED_LOGIN_PATTERN = Pattern.compile(".*Failed login.*|.*Authentication failed.*");
private static final Pattern HIGH_LOAD_PATTERN = Pattern.compile(".*load average:.*([0-9]+\\.[0-9]+).*");
public static class Alert {
public String level;
public String message;
public LocalDateTime timestamp;
public String source;
public Alert(String level, String message, String source) {
this.level = level;
this.message = message;
this.timestamp = LocalDateTime.now();
this.source = source;
}
public String toJson() {
return String.format(
"{\"level\":\"%s\",\"message\":\"%s\",\"timestamp\":\"%s\",\"source\":\"%s\"}",
level, message.replace("\"", "\\\""), timestamp.toString(), source
);
}
}
public static List analyzeLogLine(String line, String source) {
List alerts = new ArrayList<>();
if (CRITICAL_PATTERN.matcher(line).find()) {
alerts.add(new Alert("CRITICAL", line, source));
} else if (ERROR_PATTERN.matcher(line).find()) {
alerts.add(new Alert("ERROR", line, source));
}
if (FAILED_LOGIN_PATTERN.matcher(line).find()) {
alerts.add(new Alert("SECURITY", line, source));
}
Matcher loadMatcher = HIGH_LOAD_PATTERN.matcher(line);
if (loadMatcher.find()) {
double load = Double.parseDouble(loadMatcher.group(1));
if (load > 5.0) {
alerts.add(new Alert("PERFORMANCE", "High load detected: " + load, source));
}
}
return alerts;
}
// Integration with webhook-based monitoring
public static void sendToWebhook(Alert alert, String webhookUrl) throws IOException {
ProcessBuilder pb = new ProcessBuilder(
"curl", "-X", "POST",
"-H", "Content-Type: application/json",
"-d", alert.toJson(),
webhookUrl
);
pb.start();
}
public static void main(String[] args) throws IOException {
String logFile = args.length > 0 ? args[0] : "/var/log/syslog";
String webhookUrl = System.getenv("MONITORING_WEBHOOK");
Files.lines(Paths.get(logFile))
.flatMap(line -> analyzeLogLine(line, logFile).stream())
.forEach(alert -> {
System.out.println("Alert: " + alert.toJson());
if (webhookUrl != null) {
try {
sendToWebhook(alert, webhookUrl);
} catch (IOException e) {
System.err.println("Failed to send alert: " + e.getMessage());
}
}
});
}
}
Advanced Regex Techniques for Server Management
Performance Optimization
When processing large log files or real-time streams, regex performance becomes critical. Here are optimization techniques that can make the difference between a responsive system and one that grinds to a halt:
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.*;
public class OptimizedRegexProcessor {
// Pre-compile patterns for reuse
private static final Map<String, Pattern> COMPILED_PATTERNS = new ConcurrentHashMap<>();
static {
// Common server log patterns
COMPILED_PATTERNS.put("IP", Pattern.compile("\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b"));
COMPILED_PATTERNS.put("TIMESTAMP", Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"));
COMPILED_PATTERNS.put("HTTP_STATUS", Pattern.compile("\\b[1-5]\\d{2}\\b"));
COMPILED_PATTERNS.put("EMAIL", Pattern.compile("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b"));
}
// Thread-safe pattern matching
public static List findMatches(String input, String patternName) {
Pattern pattern = COMPILED_PATTERNS.get(patternName);
if (pattern == null) {
throw new IllegalArgumentException("Unknown pattern: " + patternName);
}
List matches = new ArrayList<>();
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
matches.add(matcher.group());
}
return matches;
}
// Batch processing with parallel streams
public static Map<String, Long> processLogFiles(List filePaths) {
return filePaths.parallelStream()
.flatMap(filePath -> {
try {
return Files.lines(Paths.get(filePath));
} catch (IOException e) {
System.err.println("Error reading file: " + filePath);
return Stream.empty();
}
})
.flatMap(line -> findMatches(line, "IP").stream())
.collect(Collectors.groupingBy(
ip -> ip,
Collectors.counting()
));
}
// Memory-efficient streaming for large files
public static void processLargeLogFile(String filePath, String outputPath) throws IOException {
Pattern pattern = COMPILED_PATTERNS.get("IP");
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath));
BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputPath))) {
String line;
Map<String, Integer> ipCounts = new HashMap<>();
int lineCount = 0;
while ((line = reader.readLine()) != null) {
lineCount++;
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
String ip = matcher.group();
ipCounts.merge(ip, 1, Integer::sum);
}
// Flush results every 10,000 lines to manage memory
if (lineCount % 10000 == 0) {
flushResults(writer, ipCounts);
ipCounts.clear();
System.out.println("Processed " + lineCount + " lines");
}
}
// Flush remaining results
flushResults(writer, ipCounts);
}
}
private static void flushResults(BufferedWriter writer, Map<String, Integer> results) throws IOException {
for (Map.Entry<String, Integer> entry : results.entrySet()) {
writer.write(entry.getKey() + "," + entry.getValue() + "\n");
}
writer.flush();
}
}
Real-time Log Monitoring
For real-time server monitoring, you need regex patterns that can process log streams efficiently:
import java.util.regex.*;
import java.io.*;
import java.nio.file.*;
import java.util.concurrent.*;
public class RealTimeLogMonitor {
private final ExecutorService executor = Executors.newFixedThreadPool(4);
private final Map<String, Pattern> alertPatterns = new HashMap<>();
private volatile boolean monitoring = true;
public RealTimeLogMonitor() {
// Define alert patterns
alertPatterns.put("SECURITY_BREACH",
Pattern.compile(".*(?:failed login|unauthorized access|brute force|sql injection).*", Pattern.CASE_INSENSITIVE));
alertPatterns.put("SERVER_ERROR",
Pattern.compile(".*(?:500 Internal Server Error|502 Bad Gateway|503 Service Unavailable).*"));
alertPatterns.put("HIGH_RESPONSE_TIME",
Pattern.compile(".*response_time:(\\d+).*"));
alertPatterns.put("DISK_FULL",
Pattern.compile(".*(?:disk full|no space left|filesystem full).*", Pattern.CASE_INSENSITIVE));
}
public void monitorFile(String filePath) {
executor.submit(() -> {
try {
Path path = Paths.get(filePath);
long lastPosition = Files.size(path);
while (monitoring) {
long currentSize = Files.size(path);
if (currentSize > lastPosition) {
processNewLines(path, lastPosition, currentSize);
lastPosition = currentSize;
}
Thread.sleep(1000); // Check every second
}
} catch (IOException | InterruptedException e) {
System.err.println("Error monitoring file: " + e.getMessage());
}
});
}
private void processNewLines(Path path, long fromPosition, long toPosition) throws IOException {
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "r")) {
file.seek(fromPosition);
String line;
while ((line = file.readLine()) != null && file.getFilePointer() <= toPosition) { final String logLine = line; // Process each line in parallel executor.submit(() -> analyzeLogLine(logLine));
}
}
}
private void analyzeLogLine(String line) {
for (Map.Entry<String, Pattern> entry : alertPatterns.entrySet()) {
Matcher matcher = entry.getValue().matcher(line);
if (matcher.find()) {
handleAlert(entry.getKey(), line, matcher);
}
}
}
private void handleAlert(String alertType, String line, Matcher matcher) {
String timestamp = LocalDateTime.now().toString();
switch (alertType) {
case "HIGH_RESPONSE_TIME":
int responseTime = Integer.parseInt(matcher.group(1));
if (responseTime > 5000) { // 5 seconds threshold
System.out.println("ALERT: High response time detected: " + responseTime + "ms");
// Send to monitoring system
}
break;
case "SECURITY_BREACH":
System.out.println("SECURITY ALERT: " + line);
// Immediate notification
break;
default:
System.out.println("ALERT [" + alertType + "]: " + line);
}
}
public void shutdown() {
monitoring = false;
executor.shutdown();
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
public static void main(String[] args) {
RealTimeLogMonitor monitor = new RealTimeLogMonitor();
// Monitor multiple log files
monitor.monitorFile("/var/log/apache2/access.log");
monitor.monitorFile("/var/log/apache2/error.log");
monitor.monitorFile("/var/log/auth.log");
// Shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(monitor::shutdown));
System.out.println("Real-time log monitoring started. Press Ctrl+C to stop.");
// Keep main thread alive
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
monitor.shutdown();
}
}
}
Interesting Facts and Unconventional Use Cases
Java’s regex engine has some fascinating capabilities that go beyond typical string matching. Did you know that the Java regex engine processes about 1-10 MB of text per second on modern hardware? That’s fast enough to handle most server log analysis tasks in real-time.
Here are some unconventional but incredibly useful applications:
Network Traffic Analysis
// Extract and analyze network patterns from tcpdump output
String tcpdumpPattern = "(?\\d{2}:\\d{2}:\\d{2}\\.\\d+)\\s+IP\\s+(?[\\d\\.]+)\\.(?\\d+)\\s+>\\s+(?[\\d\\.]+)\\.(?\\d+)";
Pattern networkPattern = Pattern.compile(tcpdumpPattern);
// Detect potential DDoS attacks by analyzing request patterns
String ddosPattern = "(?\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(?\\d{2}:\\d{2}:\\d{2})";
Configuration Template Processing
import java.util.regex.*;
import java.util.*;
public class ConfigTemplateProcessor {
// Process configuration templates with variable substitution
public static String processTemplate(String template, Map<String, String> variables) {
Pattern variablePattern = Pattern.compile("\\$\\{([^}]+)\\}");
StringBuffer result = new StringBuffer();
Matcher matcher = variablePattern.matcher(template);
while (matcher.find()) {
String varName = matcher.group(1);
String replacement = variables.getOrDefault(varName, "UNDEFINED_" + varName);
matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(result);
return result.toString();
}
// Generate server configurations from templates
public static void generateServerConfigs() {
String nginxTemplate = """
server {
listen ${PORT};
server_name ${DOMAIN};
root ${DOCUMENT_ROOT};
location / {
proxy_pass http://${BACKEND_HOST}:${BACKEND_PORT};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
access_log ${LOG_PATH}/access.log;
error_log ${LOG_PATH}/error.log;
}
""";
List<Map<String, String>> serverConfigs = Arrays.asList(
Map.of("PORT", "80", "DOMAIN", "api.example.com", "DOCUMENT_ROOT", "/var/www/api",
"BACKEND_HOST", "127.0.0.1", "BACKEND_PORT", "8080", "LOG_PATH", "/var/log/nginx"),
Map.of("PORT", "80", "DOMAIN", "admin.example.com", "DOCUMENT_ROOT", "/var/www/admin",
"BACKEND_HOST", "127.0.0.1", "BACKEND_PORT", "8081", "LOG_PATH", "/var/log/nginx")
);
for (int i = 0; i < serverConfigs.size(); i++) {
String config = processTemplate(nginxTemplate, serverConfigs.get(i));
System.out.println("=== Server Config " + (i + 1) + " ===");
System.out.println(config);
}
}
public static void main(String[] args) {
generateServerConfigs();
}
}
Automated Security Scanning
import java.util.regex.*;
import java.util.*;
public class SecurityScanner {
private static final Map<String, Pattern> SECURITY_PATTERNS = new HashMap<>();
static {
// SQL injection patterns
SECURITY_PATTERNS.put("SQL_INJECTION",
Pattern.compile(".*(?:'.*(?:union|select|insert|update|delete|drop|exec|script).*'|\\b(?:union|select|insert|update|delete|drop)\\b.*(?:from|where|into)\\b).*",
Pattern.CASE_INSENSITIVE));
// XSS patterns
SECURITY_PATTERNS.put("XSS",
Pattern.compile(".*<\\s*script[^>]*>.*</\\s*script\\s*>.*|.*javascript:\\s*.*|.*on\\w+\\s*=.*",
Pattern.CASE_INSENSITIVE));
// Path traversal
SECURITY_PATTERNS.put("PATH_TRAVERSAL",
Pattern.compile(".*(?:\\.\\./|\\.\\\\|%2e%2e%2f|%2e%2e%5c).*",
Pattern.CASE_INSENSITIVE));
// Suspicious user agents
SECURITY_PATTERNS.put("SUSPICIOUS_USER_AGENT",
Pattern.compile(".*(?:nikto|sqlmap|nmap|masscan|zap|burp|wget|curl).*",
Pattern.CASE_INSENSITIVE));
// Password brute force indicators
SECURITY_PATTERNS.put("BRUTE_FORCE",
Pattern.compile(".*(?:password|login|auth).*(?:failed|invalid|incorrect).*",
Pattern.CASE_INSENSITIVE));
}
public static class SecurityThreat {
public String type;
public String severity;
public String evidence;
public String sourceIP;
public LocalDateTime detectedAt;
public SecurityThreat(String type, String severity, String evidence, String sourceIP) {
this.type = type;
this.severity = severity;
this.evidence = evidence;
this.sourceIP = sourceIP;
this.detectedAt = LocalDateTime.now();
}
}
public static List scanLogEntry(String logEntry) {
List threats = new ArrayList<>();
// Extract IP address from log entry
Pattern ipPattern = Pattern.compile("\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b");
Matcher ipMatcher = ipPattern.matcher(logEntry);
String sourceIP = ipMatcher.find() ? ipMatcher.group() : "unknown";
for (Map.Entry<String, Pattern> entry : SECURITY_PATTERNS.entrySet()) {
Matcher matcher = entry.getValue().matcher(logEntry);
if (matcher.find()) {
String severity = determineSeverity(entry.getKey());
threats.add(new SecurityThreat(entry.getKey(), severity, logEntry, sourceIP));
}
}
return threats;
}
private static String determineSeverity(String threatType) {
switch (threatType) {
case "SQL_INJECTION":
case "XSS":
return "HIGH";
case "PATH_TRAVERSAL":
return "MEDIUM";
case "SUSPICIOUS_USER_AGENT":
case "BRUTE_FORCE":
return "LOW";
default:
return "UNKNOWN";
}
}
// Generate security report
public static void generateSecurityReport(List logEntries) {
Map<String, Integer> threatCounts = new HashMap<>();
Map<String, Set> threatIPs = new HashMap<>();
for (String logEntry : logEntries) {
List threats = scanLogEntry(logEntry);
for (SecurityThreat threat : threats) {
threatCounts.merge(threat.type, 1, Integer::sum);
threatIPs.computeIfAbsent(threat.type, k -> new HashSet<>()).add(threat.sourceIP);
if ("HIGH".equals(threat.severity)) {
System.out.println("HIGH SEVERITY THREAT DETECTED:");
System.out.println("Type: " + threat.type);
System.out.println("Source IP: " + threat.sourceIP);
System.out.println("Evidence: " + threat.evidence);
System.out.println("---");
}
}
}
System.out.println("SECURITY SCAN SUMMARY:");
System.out.println("=".repeat(40));
for (Map.Entry<String, Integer> entry : threatCounts.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue() + " incidents from " +
threatIPs.get(entry.getKey()).size() + " unique IPs");
}
}
public static void main(String[] args) throws IOException {
// Example usage with log file
List logEntries = Arrays.asList(
"192.168.1.100 - - [15/Oct/2023:14:30:25 +0000] \"GET /admin' UNION SELECT * FROM users-- HTTP/1.1\" 200 1234",
"10.0.0.50 - - [15/Oct/2023:14:31:00 +0000] \"GET /app?page=../../../etc/passwd HTTP/1.1\" 404 567",
"172.16.0.25 - - [15/Oct/2023:14:31:30 +0000] \"POST /login HTTP/1.1\" 401 89 \"Mozilla/5.0\" \"password=admin&user=admin\"",
"203.0.113.15 - - [15/Oct/2023:14:32:00 +0000] \"GET / HTTP/1.1\" 200 2345 \"nikto/2.1.6\""
);
generateSecurityReport(logEntries);
}
}
Automation and Scripting Possibilities
Java regex opens up incredible automation possibilities for server management. You can create intelligent monitoring systems that adapt to your infrastructure:
#!/bin/bash
# Automated server health check using Java regex
JAVA_CLASS="ServerHealthChecker"
ALERT_THRESHOLD=10
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
# Compile if needed
[ ! -f "${JAVA_CLASS}.class" ] && javac ${JAVA_CLASS}.java
# Run health check and capture output
HEALTH_REPORT=$(java $JAVA_CLASS 2>&1)
CRITICAL_COUNT=$(echo "$HEALTH_REPORT" | grep -c "CRITICAL")
if [ $CRITICAL_COUNT -gt $ALERT_THRESHOLD ]; then
# Send alert to monitoring system
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"Server health critical: $CRITICAL_COUNT issues detected\"}" \
$WEBHOOK_URL
# Trigger automated remediation
/usr/local/bin/auto-remediate.sh
fi
# Log results
echo "$(date): Health check completed - $CRITICAL_COUNT critical issues" >> /var/log/health-check.log
For VPS deployments, consider using managed VPS hosting that provides the flexibility you need for custom monitoring solutions. If you’re running enterprise-scale operations, dedicated servers offer the performance and isolation required for intensive regex processing on large log volumes.
Related Tools and Ecosystem Integration
Java regex integrates beautifully with the broader server management ecosystem:
- Apache Kafka – Use regex for stream processing and log aggregation
- Elasticsearch – Combine with Logstash for advanced log parsing
- Prometheus – Create custom metrics based on regex pattern matches
- Grafana – Visualize regex-extracted metrics in dashboards
- Jenkins – Integrate regex validation in CI/CD pipelines
- Ansible – Use regex in playbooks for configuration validation
Docker Integration Example
# Dockerfile for containerized log processor
FROM openjdk:11-jre-slim
WORKDIR /app
COPY *.java /app/
COPY *.class /app/
# Install dependencies
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Create volume for logs
VOLUME [“/logs”]
# Environment variables
ENV WEBHOOK_URL=””
ENV LOG_

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.