- Home »

Метод match в JavaScript
Парсинг строк в JavaScript — это то, с чем сталкивается любой разработчик, занимающийся автоматизацией серверных задач. Метод match()
— один из самых мощных инструментов для этой цели. Он позволяет извлекать данные из логов, конфигов, результатов команд и API-ответов. В этой статье разберём, как использовать match()
для решения практических задач на сервере, от простого поиска до сложных паттернов регулярных выражений.
Как работает метод match()
Метод match()
принимает регулярное выражение или строку и возвращает массив совпадений. Если совпадений нет — возвращает null
. Синтаксис простой:
string.match(regexp)
Есть два основных режима работы:
- Без флага g — возвращает первое совпадение с группами захвата
- С флагом g — возвращает все совпадения без групп захвата
Пример базового использования:
const log = "192.168.1.1 - - [25/Dec/2023:10:15:32 +0000] GET /api/status 200";
const ip = log.match(/\d+\.\d+\.\d+\.\d+/);
console.log(ip[0]); // 192.168.1.1
Пошаговая настройка для серверных задач
Для работы с серверными логами и конфигами на VPS создадим несколько полезных скриптов:
Шаг 1: Парсинг логов Apache/Nginx
const fs = require('fs');
// Чтение лога
const logContent = fs.readFileSync('/var/log/nginx/access.log', 'utf8');
// Парсинг IP-адресов
const ips = logContent.match(/\d+\.\d+\.\d+\.\d+/g);
console.log('Unique IPs:', [...new Set(ips)].length);
// Парсинг кодов ответов
const statusCodes = logContent.match(/\s(\d{3})\s/g);
const codes = statusCodes.map(code => code.trim());
console.log('Status codes:', codes.slice(0, 10));
Шаг 2: Извлечение данных из конфигов
// Парсинг конфига Nginx
const nginxConfig = `
server {
listen 80;
server_name example.com;
root /var/www/html;
}`;
// Извлечение server_name
const serverName = nginxConfig.match(/server_name\s+([^;]+)/);
console.log('Server name:', serverName[1]); // example.com
// Извлечение всех директив
const directives = nginxConfig.match(/(\w+)\s+([^;]+);/g);
console.log('Directives:', directives);
Шаг 3: Анализ системных команд
const { exec } = require('child_process');
exec('df -h', (error, stdout) => {
if (error) return;
// Парсинг вывода df
const diskInfo = stdout.match(/(\S+)\s+(\d+\w+)\s+(\d+\w+)\s+(\d+\w+)\s+(\d+%)\s+(\S+)/g);
diskInfo.forEach(line => {
const parts = line.match(/(\S+)\s+(\d+\w+)\s+(\d+\w+)\s+(\d+\w+)\s+(\d+%)\s+(\S+)/);
if (parts) {
console.log(`Device: ${parts[1]}, Usage: ${parts[5]}, Mount: ${parts[6]}`);
}
});
});
Практические примеры и кейсы
Задача | Регулярное выражение | Результат |
---|---|---|
Извлечение IP-адресов | /\d+\.\d+\.\d+\.\d+/g | [‘192.168.1.1’, ‘10.0.0.1’] |
Email-адреса | /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g | [‘user@example.com’] |
HTTP коды ответов | /\s([1-5]\d{2})\s/g | [‘200’, ‘404’, ‘500’] |
Доменные имена | /(?:https?:\/\/)?(?:www\.)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g | [‘example.com’, ‘test.org’] |
Положительные примеры
// Мониторинг ошибок в логах
const errorLog = `
[ERROR] 2023-12-25 10:15:32 Database connection failed
[WARN] 2023-12-25 10:16:45 High memory usage: 85%
[ERROR] 2023-12-25 10:17:12 API timeout after 30s
`;
// Извлечение только ошибок
const errors = errorLog.match(/\[ERROR\][^\n]+/g);
console.log('Errors found:', errors.length);
// Извлечение времени ошибок
const errorTimes = errorLog.match(/\[ERROR\]\s+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})/g);
console.log('Error times:', errorTimes);
Обработка граничных случаев
function safeMatch(text, pattern) {
const result = text.match(pattern);
return result || []; // Возвращаем пустой массив вместо null
}
// Безопасный парсинг конфигов
const config = "timeout=30\nretries=3\nhost=localhost";
const timeout = safeMatch(config, /timeout=(\d+)/);
const port = safeMatch(config, /port=(\d+)/); // Не найдено
console.log('Timeout:', timeout[1] || 'default');
console.log('Port:', port[1] || '80'); // Значение по умолчанию
Сравнение с альтернативными методами
Метод | Производительность | Гибкость | Сложность |
---|---|---|---|
match() | Высокая | Очень высокая | Средняя |
split() | Очень высокая | Низкая | Низкая |
indexOf() | Максимальная | Очень низкая | Очень низкая |
Внешние парсеры | Низкая | Высокая | Высокая |
Интеграция с другими инструментами
Метод match()
отлично сочетается с другими JavaScript-инструментами для автоматизации серверов:
// Интеграция с Node.js fs для мониторинга
const fs = require('fs');
const path = require('path');
function monitorLogs(logPath) {
fs.watchFile(logPath, (curr, prev) => {
const content = fs.readFileSync(logPath, 'utf8');
const newErrors = content.match(/\[ERROR\][^\n]+/g) || [];
if (newErrors.length > 0) {
console.log('New errors detected:', newErrors.length);
// Отправка уведомления
}
});
}
// Интеграция с cron для регулярных проверок
const cron = require('node-cron');
cron.schedule('*/5 * * * *', () => {
const logFile = '/var/log/app.log';
if (fs.existsSync(logFile)) {
const content = fs.readFileSync(logFile, 'utf8');
const criticalErrors = content.match(/\[CRITICAL\][^\n]+/g);
if (criticalErrors && criticalErrors.length > 0) {
console.log('ALERT: Critical errors found!');
}
}
});
Автоматизация и скрипты
Создадим комплексный скрипт для мониторинга сервера на выделенном сервере:
#!/usr/bin/env node
const fs = require('fs');
const { exec } = require('child_process');
class ServerMonitor {
constructor() {
this.logPaths = [
'/var/log/nginx/access.log',
'/var/log/nginx/error.log',
'/var/log/syslog'
];
}
analyzeTraffic() {
const accessLog = fs.readFileSync(this.logPaths[0], 'utf8');
// Анализ IP-адресов
const ips = accessLog.match(/^\d+\.\d+\.\d+\.\d+/gm) || [];
const uniqueIPs = [...new Set(ips)];
// Анализ User-Agent
const userAgents = accessLog.match(/"Mozilla[^"]+"/g) || [];
const bots = userAgents.filter(ua => ua.match(/bot|crawler|spider/i));
return {
totalRequests: ips.length,
uniqueVisitors: uniqueIPs.length,
botRequests: bots.length
};
}
checkErrors() {
const errorLog = fs.readFileSync(this.logPaths[1], 'utf8');
const errors = errorLog.match(/\[error\][^\n]+/gi) || [];
return {
totalErrors: errors.length,
recentErrors: errors.slice(-10) // Последние 10 ошибок
};
}
generateReport() {
const traffic = this.analyzeTraffic();
const errors = this.checkErrors();
console.log('=== Server Report ===');
console.log(`Total requests: ${traffic.totalRequests}`);
console.log(`Unique visitors: ${traffic.uniqueVisitors}`);
console.log(`Bot requests: ${traffic.botRequests}`);
console.log(`Total errors: ${errors.totalErrors}`);
if (errors.recentErrors.length > 0) {
console.log('\nRecent errors:');
errors.recentErrors.forEach((error, index) => {
console.log(`${index + 1}. ${error}`);
});
}
}
}
const monitor = new ServerMonitor();
monitor.generateReport();
Продвинутые техники
Именованные группы захвата
// Современный подход с именованными группами
const logEntry = "192.168.1.1 - - [25/Dec/2023:10:15:32 +0000] GET /api/users 200 1234";
const pattern = /(?<ip>\d+\.\d+\.\d+\.\d+).*?\[(?<date>[^\]]+)\]\s+(?<method>\w+)\s+(?<path>\S+)\s+(?<status>\d+)\s+(?<size>\d+)/;
const match = logEntry.match(pattern);
if (match) {
console.log('IP:', match.groups.ip);
console.log('Date:', match.groups.date);
console.log('Method:', match.groups.method);
console.log('Path:', match.groups.path);
console.log('Status:', match.groups.status);
console.log('Size:', match.groups.size);
}
Производительность и оптимизация
// Компиляция регулярных выражений для повторного использования
const IP_REGEX = /\d+\.\d+\.\d+\.\d+/g;
const EMAIL_REGEX = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
function optimizedParsing(logContent) {
// Сброс lastIndex для глобальных регулярок
IP_REGEX.lastIndex = 0;
EMAIL_REGEX.lastIndex = 0;
const ips = logContent.match(IP_REGEX) || [];
const emails = logContent.match(EMAIL_REGEX) || [];
return { ips, emails };
}
// Бенчмарк
console.time('parsing');
const result = optimizedParsing(largeLogFile);
console.timeEnd('parsing');
Интересные факты и нестандартные применения
- Валидация конфигов —
match()
можно использовать для проверки синтаксиса конфигурационных файлов перед их применением - Автоматическое обновление — парсинг версий из package.json или composer.json для автоматических обновлений
- Безопасность — обнаружение подозрительных паттернов в логах (SQL-инъекции, XSS-атаки)
- Мониторинг производительности — извлечение времени выполнения запросов для анализа bottleneck’ов
// Детектор атак
function detectAttacks(accessLog) {
const sqlInjection = accessLog.match(/union\s+select|drop\s+table|insert\s+into/gi) || [];
const xss = accessLog.match(/<script|javascript:|onload=/gi) || [];
const bruteForce = accessLog.match(/wp-login\.php|admin\/login/gi) || [];
return {
sqlAttempts: sqlInjection.length,
xssAttempts: xss.length,
bruteForceAttempts: bruteForce.length
};
}
// Парсинг времени выполнения из логов приложения
function parseExecutionTime(appLog) {
const timings = appLog.match(/Execution time:\s+(\d+\.?\d*)\s*ms/g) || [];
const times = timings.map(t => parseFloat(t.match(/(\d+\.?\d*)/)[1]));
return {
average: times.reduce((a, b) => a + b, 0) / times.length,
max: Math.max(...times),
min: Math.min(...times)
};
}
Полезные ресурсы
- MDN документация по match()
- Regex101 — тестирование регулярных выражений
- RegExr — ещё один отличный инструмент для regex
Заключение и рекомендации
Метод match()
— это мощный инструмент для системного администратора и DevOps-инженера. Он позволяет быстро извлекать нужную информацию из логов, конфигов и вывода системных команд. Основные рекомендации:
- Используйте для анализа логов — идеально подходит для мониторинга и алертинга
- Компилируйте регулярки — для повторного использования создавайте константы
- Обрабатывайте null — всегда проверяйте результат на null или используйте оператор ||
- Именованные группы — для сложных паттернов используйте именованные группы захвата
- Тестируйте производительность — на больших файлах регулярные выражения могут тормозить
Для серверных задач match()
незаменим при создании скриптов мониторинга, автоматизации и анализа данных. Он отлично интегрируется с Node.js и другими инструментами, делая его идеальным выбором для DevOps-автоматизации.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.