Что делает cut и чем он прост
Команда cut вырезает из каждой строки ввода часть: либо поля, разделённые определённым символом, либо символы по номерам позиций. Она ничего не запоминает между строками, не умеет условий и вычислений. В этом и её смысл: когда разделитель понятен и стабилен, cut короче и быстрее читается, чем awk.
Данные cut получает из файла или по конвейеру, а результат печатает в стандартный вывод. Поэтому её часто ставят в середину цепочки: сначала что-то выбирает grep, потом cut оставляет нужный кусок, потом sort и uniq считают повторы.
Подходит она для файлов и выводов с чёткой структурой: записи через двоеточие, значения через запятую, пары «ключ=значение», данные с табуляцией. Хуже подходит для вывода, где столбцы выровнены переменным числом пробелов: как раз так выглядят ss, netstat и ps. Для них ниже разобран другой приём, а ещё есть awk.
Три ключа: -d, -f и -c
Всего три ключа закрывают почти все случаи, и их удобно запомнить через таблицу.
| Ключ | Назначение | Пример |
|---|---|---|
| -d | символ-разделитель, по умолчанию табуляция | -d: или -d, |
| -f | номера полей | -f1, -f1,3, -f2- |
| -c | позиции символов | -c1-8, -c5- |
Номера полей и позиций начинаются с единицы. Диапазон записывают через дефис: 2-4 означает поля со второго по четвёртое, 2- от второго до конца строки, -3 с первого по третье. Несколько отдельных номеров перечисляют через запятую: -f1,3.
Разделитель по умолчанию табуляция, а не пробел. Это сбивает: cut -f1 на тексте с пробелами выведет всю строку целиком, потому что табуляций в ней нет. Строки, где разделителя нет вообще, cut по умолчанию печатает как есть; чтобы их пропускать, добавляют ключ -s. Если разделитель пробел, его указывают в кавычках: -d' '.
Примеры на файлах и выводе сетевых команд
Файл /etc/resolv.conf на многих Linux-системах содержит строки вида «nameserver 192.0.2.53». Чтобы получить только адреса: grep ^nameserver /etc/resolv.conf | cut -d' ' -f2. Здесь разделитель одиночный пробел, и cut справляется, потому что внутри строки он единственный.
Адрес из пары «адрес:порт» вырезают по двоеточию: echo 198.51.100.7:443 | cut -d: -f1 даёт адрес, а -f2 порт. Для IPv4 это работает, а для IPv6 нет: в адресе много двоеточий, и поля разъедутся.
Первые символы строки берёт -c. Например, ip -o link | cut -c1-40 обрежет слишком длинные строки до сорока символов, чтобы они помещались на экране. Это грубый приём: он режет и посреди слова.
Список имён пользователей из файла с двоеточиями: cut -d: -f1 /etc/passwd. Если нужно взять все поля, кроме одного, у GNU-версии есть ключ --complement, но он есть не везде, в версии из macOS его нет, поэтому в переносимых командах лучше перечислять поля явно.
Выровненные столбцы: почему cut ошибается
В выводе вроде ss -tan или ps столбцы выровнены пробелами, и между значениями их может быть несколько. Для cut каждый пробел это отдельный разделитель, поэтому между двумя пробелами возникает пустое поле. В результате номер поля сдвигается: в разных строках один и тот же столбец оказывается под разными номерами.
Есть два рабочих выхода.
- Сжать серию пробелов в один с помощью tr -s ' ': ss -tan | tr -s ' ' | cut -d' ' -f5. Ключ -s у tr заменяет повторяющиеся подряд символы одним. Следите за ведущими пробелами в начале строки: если они есть, первое поле окажется пустым, и все номера сдвинутся.
- Воспользоваться awk, который по умолчанию сам сворачивает пробелы: ss -tan | awk '{print $5}'. Если столбцов много или данные неровные, результат стабильнее.
В итоге правило простое: стабильный одиночный разделитель, как в файлах конфигурации или CSV, это территория cut. Выровненный текст из утилит диагностики лучше отдавать awk.
Проверка и типичные ошибки
Если cut вернул пустые строки или целые строки вместо поля, проверьте три вещи в таком порядке.
- Разделитель: действительно ли в данных стоит тот символ, который указан в -d. Невидимая разница между пробелом и табуляцией встречается часто. Просмотреть невидимые символы можно командой cat -A на GNU-системах.
- Номер поля: нумерация с единицы, и пустые поля тоже считаются.
- Кавычки: разделитель-пробел и спецсимволы оболочки берут в одинарные кавычки.
Отдельный случай — символы вне ASCII. Ключ -c считает байты или символы в зависимости от реализации и настроек локали, а для многобайтных символов, например кириллицы, поведение может отличаться. Поэтому для текста на русском позиционная нарезка надёжна не всегда. Если нужно резать по символам, смотрите справку cut и при необходимости ключ -b или другую утилиту.
Для сложного разбора, когда нужно и условие, и выбор нескольких полей сразу, не растягивайте цепочку из cut: переходите на awk.
Связки cut с соседними утилитами
cut редко работает в одиночку. Вот несколько сочетаний, где он на своём месте, и уточнения, на что смотреть.
- ip -4 -o addr | awk '{print $4}' | cut -d/ -f1 — из пары «адрес/маска» остаётся только адрес. Разделитель косая черта не требует кавычек, но в сложных случаях их ставят.
- echo 203.0.113.25 | cut -d. -f1-3 — первые три октета адреса, то есть префикс сети в привычной записи. Для маски длиннее или короче этот приём не годится: он режет по точкам, а не по битам.
- grep ^nameserver /etc/resolv.conf | cut -d' ' -f2 | sort -u — список уникальных DNS-серверов из файла.
- cut -d, -f2 файл.csv | sort | uniq -c — сводка по второму столбцу CSV-файла, если в данных нет запятых внутри кавычек.
Последнее ограничение важно: cut не понимает кавычек и экранирования, он разрезает строку по каждому разделителю механически. Для настоящего CSV с запятыми внутри значений нужны другие инструменты, а для логов и выводов диагностических команд такой простоты обычно хватает.
Если вы не уверены, что разделитель в данных один и тот же во всех строках, просмотрите несколько строк до и после нужной, а не только первую: заголовок или служебные строки нередко устроены иначе, и поле в них окажется не там.