Linux-инструменты для анализа кода и текста: от grep до ast-grep
Эти инструменты превращают терминал в полноценную среду анализа кода — без IDE, без плагинов, без LLM. От поиска паттернов до подсчёта сложности и поиска дубликатов.
Базовые: grep, awk, sed
grep — поиск по содержимому
# Рекурсивный поиск TODO/FIXME
grep -rn "TODO\|FIXME" --include="*.py" .
# Поиск функций с подсчётом
grep -c "def " *.py
# Поиск с контекстом (2 строки до и после)
grep -C 2 "import pandas" *.py
# Поиск с подсветкой и номерами строк
grep -rn --color=always "class.*:" --include="*.py" .
awk — обработка структурированного текста
# Статистика по длине строк кода
awk '{print length, $0}' script.py | sort -rn | head
# Подсчёт импортов по модулям
grep "^import\|^from" *.py | awk '{print $2}' | sort | uniq -c
# Анализ CSV: третья колонка, где вторая > 100
awk -F',' '$2 > 100 {print $3}' data.csv
# Подсчёт циклов и условий (приблизительная сложность)
awk '/if |for |while / {count++} END {print "Complexity:", count}' script.py
sed — потоковое редактирование
# Удаление комментариев (подготовка для LLM)
sed 's/#.*$//' script.py | sed '/^$/d'
# Замена множественных пробелов
sed 's/ */ /g' messy_code.txt
# Извлечение строк между маркерами
sed -n '/START/,/END/p' logfile.txt
Структура проекта
| Инструмент | Команда | Что делает |
|---|---|---|
| tree | tree -L 3 -I 'node_modules|.git' |
Дерево проекта с фильтрацией |
| tree | tree -h -s --du |
Дерево с размерами |
| fd | fd -e py -x wc -l {} |
Подсчёт строк в каждом Python-файле |
| fd | fd -t d -d 2 |
Все директории на глубину 2 |
| fd | fd TODO --type f |
Поиск файлов с TODO |
| exa/eza | eza -la --tree -L 2 --git |
Современная замена ls с деревом |
fd — современная замена find. Быстрее, дружелюбный вывод, умные дефолты (игнорирует .git, node_modules).
# Установка
sudo apt install fd-find # Ubuntu
# или
cargo install fd-find
Поиск по содержимому: ripgrep
ripgrep (rg) — современная замена grep. В 5–10 раз быстрее на больших проектах.
# Поиск всех вызовов функции во всех файлах
rg "function_name\(" --type py
# Поиск с контекстом
rg -C 3 "TODO" --type ts
# Подсчёт вхождений по файлам
rg -c "import" --type py | sort -t: -k2 -rn
# Поиск с заменой (dry-run)
rg "old_api" --type py -l | xargs sed -i 's/old_api/new_api/g'
# Исключить файлы и директории
rg "pattern" -g '!*.min.js' -g '!dist/'
Статистика кода: tokei, cloc, scc
Эти утилиты считают строки кода, комментарии и пустые строки по языкам.
# tokei — самый быстрый (Rust), красивый вывод
tokei . --sort lines
# cloc — классика, поддерживает 300+ языков
cloc . --by-file
# scc — ещё быстрее, сложностные метрики
scc . --complexity
Сравнение на проекте из 100K строк:
| Инструмент | Время | Языков |
|---|---|---|
| tokei | 0.3 с | Rust |
| scc | 0.2 с | Go |
| cloc | 15 с | Perl |
scc также оценивает когнитивную сложность по строкам.
JSON: jq
# Извлечение поля из API-ответа
curl -s https://api.example.com/data | jq '.items[].name'
# Фильтрация
jq '.[] | select(.status == "error")' errors.json
# Группировка и подсчёт
jq 'group_by(.severity) | map({level: .[0].severity, count: length})' issues.json
# Переформатирование
jq '{total: .count, names: [.items[].name]}' data.json
# Слияние нескольких JSON-файлов
jq -s 'add' file1.json file2.json file3.json
AST-анализ: ast-grep, semgrep, comby
В отличие от grep, эти инструменты понимают синтаксическую структуру кода.
ast-grep — поиск по AST (абстрактному синтаксическому дереву)
# Найти все вызовы console.log с любым аргументом
ast-grep -p "console.log($$$)" --lang js
# Найти присваивания без тип-аннотаций
ast-grep -p "var $A = $_" --lang py
# Замена с сохранением форматирования
ast-grep -p "oldFunction($$$ARGS)" -r "newFunction($$$ARGS)" --lang ts
semgrep — поиск паттернов кода
# Поиск использования eval (потенциальная уязвимость)
semgrep -e 'eval(...)' --lang py
# Поиск хардкоженных секретов
semgrep --config "p/secrets" .
# Собственный rule для поиска опасных паттернов
semgrep -e 'pickle.loads(...)' --lang py
# Генерация SARIF-отчёта для CI
semgrep --config auto --sarif -o results.sarif .
comby — структурный поиск и замена
# Замена во всех языках
comby 'console.log(:[args])' 'logger.info(:[args])' -in-place
# Поиск с контекстом
comby ':[f](:[args])' '' -match-only -count
Сложность кода: radon, lizard, flake8, pylint
radon (Python)
# Цикломатическая сложность
radon cc . -a -s
# Индекс поддерживаемости
radon mi . -s
# Сырые метрики (LOC, комментарии)
radon raw .
lizard (мультиязычный)
# Сложность всех файлов в проекте
lizard . -l python
# Только функции со сложностью > 10
lizard . -C 10
# HTML-отчёт
lizard . --html > report.html
mypy, pyright, pyre (Type Checking)
mypy src/ --strict # Строгая проверка типов
pyright --outputjson src/ # JSON для CI
pyre check # Facebook-овский статический анализ
Зависимости: madge, pipdeptree, dependency-cruiser
# madge — граф зависимостей (JS/TS)
madge --image graph.svg src/index.ts
madge --circular src/ # Поиск циклических зависимостей
# pipdeptree — дерево зависимостей Python
pipdeptree --warn silence | grep -E '^\w+'
# dependency-cruiser — ещё мощнее для JS/TS
depcruise --include-only "^src" --output-type dot src | dot -T svg > deps.svg
depcruise src --validate .dependency-cruiser.js # CI-проверка
Дубликаты: jscpd
# Поиск дубликатов во всём проекте
jscpd . --min-tokens 50 --min-lines 5
# Только для Python
jscpd . --pattern "**/*.py" --reporters html,json
# Для CI: порог 5% дублирования
jscpd . --threshold 5
Безопасность: gitleaks, trivy, syft
# gitleaks — поиск секретов в git-истории
gitleaks detect --source . --verbose
# trivy — сканирование уязвимостей
trivy fs . --scanners vuln,secret,misconfig
# syft — SBOM (Software Bill of Materials)
syft . -o json > sbom.json
Готовые пайплайны
Быстрый аудит нового проекта
#!/bin/bash
# Полный аудит проекта за 30 секунд
PROJECT_DIR="${1:-.}"
echo "=== СТРУКТУРА ==="
tree -L 3 -I 'node_modules|.git|__pycache__|venv|build' "$PROJECT_DIR"
echo -e "\n=== СТАТИСТИКА ==="
tokei "$PROJECT_DIR" --sort lines | head -20
echo -e "\n=== ЦИКЛОМАТИЧЕСКАЯ СЛОЖНОСТЬ (топ-10) ==="
radon cc "$PROJECT_DIR" --min B -s 2>/dev/null | head -20 || \
lizard "$PROJECT_DIR" -C 10 2>/dev/null | head -20
echo -e "\n=== ДУБЛИКАТЫ ==="
jscpd "$PROJECT_DIR" --min-tokens 50 --min-lines 5 --silent 2>/dev/null
echo -e "\n=== ПОИСК СЕКРЕТОВ ==="
gitleaks detect --source "$PROJECT_DIR" --no-git -v 2>/dev/null
echo -e "\n=== ЦИКЛИЧЕСКИЕ ЗАВИСИМОСТИ ==="
madge --circular "$PROJECT_DIR/src" 2>/dev/null
Поисково-аналитический пайплайн
#!/bin/bash
# Найти файл → проанализировать содержимое → сохранить отчёт
QUERY="${1:?Укажите поисковый запрос}"
OUTPUT="${2:-report.md}"
echo "# Анализ по запросу: $QUERY" > "$OUTPUT"
echo "**Дата:** $(date)" >> "$OUTPUT"
echo "" >> "$OUTPUT"
# 1. Поиск релевантных файлов
echo "## 1. Файлы, содержащие '$QUERY'" >> "$OUTPUT"
echo '```' >> "$OUTPUT"
rg -l "$QUERY" --type-add 'code:*.{py,js,ts,rs,go}' --type code . >> "$OUTPUT"
echo '```' >> "$OUTPUT"
echo "" >> "$OUTPUT"
# 2. Подсчёт вхождений по файлам
echo "## 2. Частота по файлам" >> "$OUTPUT"
echo '```' >> "$OUTPUT"
rg -c "$QUERY" --type-add 'code:*.{py,js,ts,rs,go}' --type code . | \
sort -t: -k2 -rn >> "$OUTPUT"
echo '```' >> "$OUTPUT"
echo "" >> "$OUTPUT"
# 3. Контекст
echo "## 3. Контекст использования" >> "$OUTPUT"
echo '```' >> "$OUTPUT"
rg -C 1 "$QUERY" --type-add 'code:*.{py,js,ts,rs,go}' --type code . \
2>/dev/null | head -100 >> "$OUTPUT"
echo '```' >> "$OUTPUT"
echo "Отчёт сохранён в $OUTPUT"
Шпаргалка: что и когда использовать
| Задача | Инструмент | Команда |
|---|---|---|
| Поиск по содержимому | ripgrep | rg "pattern" --type py |
| Поиск по AST | ast-grep | ast-grep -p "pattern" --lang py |
| Поиск уязвимостей | semgrep | semgrep --config auto |
| Статистика кода | tokei/scc | tokei . --sort lines |
| Структура проекта | tree/fd | fd -t d -d 3 |
| Цикломатическая сложность | radon/lizard | radon cc . -a |
| Дубликаты кода | jscpd | jscpd . --min-tokens 50 |
| Зависимости | madge/pipdeptree | madge --circular src/ |
| Секреты в коде | gitleaks | gitleaks detect -v |
| JSON-анализ | jq | jq '.items[] | .name' |
| Замена по AST | comby | comby 'old(:[x])' 'new(:[x])' |