Два вопроса, на которые отвечают head и wc
Когда команда печатает длинный список, обычно интересуют две вещи. Первая: что в начале списка, особенно если он отсортирован по важности. Вторая: сколько всего строк. На первый вопрос отвечает head, на второй wc -l. Обе утилиты крошечные, но в конвейерах встречаются постоянно.
head читает поток и печатает только начало, остальное отбрасывает. Это удобно, когда нужен короткий образец вывода или десять самых частых значений после сортировки. wc (от word count) считает строки, слова и байты. Для диагностики чаще всего нужен ключ -l, он выводит число строк.
Обе утилиты не задают вопросов о смысле данных: wc -l считает символы перевода строки, а не соединения, адреса или записи. Поэтому, получив число, сверяйте, что именно оно считает: например, не входит ли в него строка заголовка таблицы.
Ключи head и wc
У обеих утилит есть небольшой набор ключей, который закрывает повседневные задачи.
| Команда | Что делает |
|---|---|
| head файл | первые 10 строк |
| head -n 3 файл | первые 3 строки |
| head -c 100 файл | первые 100 байт |
| wc -l файл | число строк, перед именем файла |
| wc -w файл | число слов |
| wc -c файл | число байт |
| wc -l < файл | число строк без имени файла |
Запись wc -l < файл удобна, когда число нужно подставить в другую команду: оболочка передаёт файл на ввод, и wc не знает его имени, а значит, не печатает его. При чтении из конвейера имени тоже нет: ss -tan | wc -l выведет только число. На macOS число обычно дополняется пробелами слева для выравнивания; для сравнения чисел в скриптах это не мешает, а для печати можно убрать пробелы через tr -d ' '.
Ключ -n у head принимает и отрицательное число в GNU-версии, где head -n -1 означает «все строки, кроме последней», но в macOS такая форма может не работать, и переносимые команды её избегают.
Подсчёт на выводе сетевых команд
Примеры, где подсчёт строк отвечает на практический вопрос.
- Число сокетов: ss -tan | wc -l. В результат входит строка заголовка, поэтому реальных сокетов на единицу меньше. Чтобы получить точное число, вычтите единицу или отрежьте заголовок: ss -tan | tail -n +2 | wc -l.
- Число установленных соединений без путаницы с заголовком: ss -tan | grep -c ESTAB. Здесь grep сам считает подходящие строки.
- Число записей в таблице соседей: ip neigh | wc -l. Заголовка у ip neigh нет, поэтому число точное.
- Число маршрутов: ip route | wc -l.
- Число интерфейсов в однострочном выводе: ip -o link | wc -l. Ключ -o выводит каждый интерфейс одной строкой.
- Число адресов, которые вернул dig: dig +short example.com | wc -l. Если ответ содержит псевдоним CNAME, он тоже занимает строку.
Последний пример показывает типичную неточность: wc -l считает строки, а не «адреса». Поэтому описывайте результат словами «число строк вывода» и проверяйте, чем именно заполнены эти строки.
head в цепочках: топ списка и образец вывода
head чаще всего стоит в конце цепочки после сортировки. Если вы посчитали повторы через sort | uniq -c | sort -rn, то head -n 10 оставит десять самых частых значений. Это быстрый способ превратить длинный отчёт в короткий.
Второе назначение — образец. Перед тем как разбирать файл большого журнала, посмотрите на его начало: head -n 5 файл. Вы увидите формат строк, разделитель и наличие заголовка, а это определяет, как писать дальше awk или cut.
Третье — защита от лишнего вывода. Команда, которая может напечатать тысячи строк, часто безопаснее в сочетании с head: ip route | head -n 20. При этом знайте особенность: когда head получил нужное число строк и завершился, предыдущая команда в конвейере может получить сигнал о закрытом канале и тоже остановиться. Для коротких команд это незаметно, а для долгих означает, что вы не увидите конец вывода.
Если вам нужен конец, а не начало, берут tail. Пара head и tail позволяет вырезать середину: head -n 20 файл | tail -n 5 покажет строки с шестнадцатой по двадцатую.
Типичные ошибки подсчёта
Заголовок таблицы. Частая причина «лишней единицы». Если команда печатает шапку, wc -l посчитает и её. Отрезайте шапку через tail -n +2 или считайте только нужные строки через grep -c.
Пустые строки. Они тоже считаются. Если в данных есть пустые разделители, число строк завышено. Уберите их через grep -v '^$', а затем считайте.
Нет перевода строки в конце. Если последняя строка не заканчивается символом перевода строки, wc -l её не учтёт. Для вывода стандартных утилит это бывает редко, но в самодельных файлах встречается.
Длинные строки и перенос. На экране строка может занимать две визуальные строки, но wc считает её за одну. Число визуальных строк и число строк данных не совпадают, и сравнивать их нельзя.
Подсчёт в конвейере с -c у grep и wc -l даёт одинаковый результат на одном и том же наборе, и это полезная проверка: если числа различаются, значит, в цепочке что-то отфильтровалось. Расхождение подсказывает, где искать причину.
Сравнение до и после: как использовать число строк
Число строк само по себе мало что говорит, зато разница между двумя замерами помогает увидеть изменение. Запишите число перед действием и после него: например, число записей ip neigh до подключения нового устройства и после. Если число выросло, в таблице соседей появился новый адрес.
Чтобы замеры были сопоставимы, считайте одной и той же командой, с теми же фильтрами и в похожих условиях. Если в первый раз вы считали ss -tan | wc -l, а во второй ss -tan | grep -c ESTAB, сравнивать результаты нельзя: это разные величины.
Записывайте время и команду рядом с числом. Через час вы не вспомните, что именно считали, а число без подписи бесполезно. Простой способ вести запись: дописывать результат в файл через tee -a, предварительно добавив строку с датой.
Для регулярного наблюдения число можно выводить повторно командой watch, а для сохранения истории сочетать date и wc -l в небольшом скрипте. Но помните ограничение метода: изменение числа строк показывает, что что-то изменилось, а не объясняет причину. Для причины смотрите на сами строки: какие именно записи появились или исчезли.