Используйте пробел в качестве разделителя с командой cut

328

Я хочу использовать пробел в качестве разделителя с cutкомандой.

Какой синтаксис я могу использовать для этого?

Jaelebi
источник
42
Неправда, справочная страница для cut не объясняет этого и, как правило, не информативна
UncleZeiv 5.10.10
2
Кроме того, «сокращение информации» не является улучшением в этом случае.
Кардифф космический человек
3
@ mklement0, если я вспоминаю, я отвечал на комментарий, который с тех пор был удален, на который был отклонен этот вопрос как ответ на странице руководства, что, на мой взгляд, было "неверным", несмотря на то, что для этого были веские причины или нет - сейчас, хотя я допускаю, что для такого недостатка информации может быть веская причина, я все же думаю, что документация без примеров общего использования часто, по крайней мере, раздражает, а
иногда и
3
@UncleZeiv Понял; Спасибо за разъяснение; учитывая интерес к этому вопросу, можно предположить, что этой manстраницы недостаточно. Давайте посмотрим: « -d delimИспользуйте delimв качестве символа разделителя полей вместо символа табуляции». (BSD cut, но версия GNU и спецификация POSIX в значительной степени утверждают одно и то же). Использование оболочки для вызова cut- типичный случай - поэтому требует, чтобы вы знали, как обычно передавать пробел в качестве аргумента, используя синтаксис оболочки , что, возможно, не cutявляется работой man-страницы. Однако примеры из реальной жизни всегда помогают, а в справочной странице GNU их нет.
mklement0
4
хотя выбранный ответ является технически правильным, рассмотрите возможность выбора более свежего и всеобъемлющего ответа @ mklement0 в качестве канонического ответа, чтобы он отфильтровывался вверх.
Дэвид Лебауэр

Ответы:

367
cut -d ' ' -f 2

Где 2 - номер поля, которое вы хотите разделить пробелом.

RichieHindle
источник
2
Можете ли вы указать cut использовать любое число определенного символа в качестве разделителя, как в RegEx? например, любое количество пробелов, например, \ s +
амфибия
3
@ foampile Нет, я не верю, что ты можешь.
Джонатан Хартли
6
Вы не можете использовать регулярные выражения с cut, но вы можете с помощью cutsкоторых пытается «исправить» все cutограничения: github.com/arielf/cuts
arielf
Вы можете получить каждое третье поле, разделенное пробелом? как cut -d ' ' -f 3,6,9,12,15,18без указания каждого номера?
Monocito
169

Обычно, если вы используете пробел в качестве разделителя, вы хотите рассматривать несколько пробелов как один, потому что вы анализируете выходные данные команды, выравнивающей некоторые столбцы с пробелами. (и поиск в Google это приводит меня сюда)

В этом случае одной cutкоманды недостаточно, и вам нужно использовать:

tr -s ' ' | cut -d ' ' -f 2

Или

awk '{print $2}'
BeniBela
источник
2
Спасибо за пример использования awk, именно то, что мне было нужно.
Спазм
44

Дополнять существующие полезные ответы; подсказка к QZ Поддержка за то, что я рекомендую опубликовать отдельный ответ:

Здесь действуют два разных механизма :

  • (а) является ли cut сам по себе требует разделителя (пространства, в данном случае) передается -dвозможности быть отдельным аргументом или является ли это приемлемо , чтобы добавить его непосредственно к -d.

  • (б) как оболочка обычно анализирует аргументы перед передачей их вызываемой команде.

(а) отвечает цитата из руководств POSIX для коммунальных услуг (выделено мое)

Если в ОПИСАНИИ стандартной утилиты показан параметр с обязательным аргументом option [...], то соответствующее приложение должно использовать отдельные аргументы для этого параметра и его аргумента option . Однако соответствующая реализация также должна позволять приложениям указывать параметр и параметр-аргумент в одной строке аргумента без промежуточных символов .

Другими словами: в этом случае, поскольку -dпараметр-аргумент является обязательным , вы можете выбрать , указывать ли разделитель следующим образом :

  • (s) ИЛИ: отдельный аргумент
  • (d) ИЛИ: как значение, непосредственно связанное с-d .

После того, как вы выбрали (s) или (d), именно строковый литеральный синтаксический анализ оболочки - (b) - имеет значение:

  • При подходе (ях) все следующие формы эквивалентны:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • При подходе (d) все следующие формы эквивалентны:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Эквивалентность объясняется оболочкой строковой литеральной обработкой :

Все приведенные выше решения приводят к появлению точно такой же строки (в каждой группе) к тому времени, когда cutони их увидят :

  • (s) : cutвидит в -dкачестве своего собственного аргумента отдельный аргумент, содержащий пробел - без кавычек или \префиксов !.

  • (d) : cutвидит -d плюс пробел - без кавычек или \префиксов! - как часть того же аргумента.

Причина, по которой формы в соответствующих группах в конечном итоге идентичны, двояка, в зависимости от того, как оболочка анализирует строковые литералы :

  • Оболочка позволяет указывать литерал как есть через механизм, называемый цитированием , который может принимать несколько форм :
    • строки в одинарных кавычках : содержимое внутри '...'воспринимается буквально и образует единый аргумент
    • строки в двойных кавычках : содержимое внутри "..."также формирует один аргумент, но подвергается интерполяции (расширяет ссылки на переменные, такие как $varподстановки команд ( $(...)или `...`) или арифметические расширения ( $(( ... ))).
    • \-цитирование отдельных символов : \предшествующий одному символу этот символ интерпретируется как литерал.
  • Цитирование дополняется удалением кавычек , что означает, что после того, как оболочка проанализировала командную строку, она удаляет символы кавычек из аргументов (включающие '...'или "..."или \экземпляры) - таким образом, вызываемая команда никогда не видит символы кавычек .
mklement0
источник
36

Вы также можете сказать:

cut -d\  -f 2

Обратите внимание, что после обратной косой черты есть два пробела.

Чес. Owens
источник
30
Человек, который знает, что «\» убегает от следующего символа, будет очень осторожен, чтобы заметить, что будет дальше. Использование '\' для экранирования таких символов - очень распространенная идиома.
Джонатан Хартли
3
@ Джонатан Хартли, как правило, большинство кодов на самом деле нечитаемы :)
Лука Боррионе
1
С точки зрения Linux / Unix, это \ была моя первая попытка, и она сработала. Я согласен, что это менее очевидно по сравнению с ' ', но я уверен, что многие рады прочитать это здесь как подтверждение поведения. Для лучшего понимания смотрите комментарий @ mklement0 ниже.
Tresf
@JonathanHartley исправление: « эгоист, который знает, что« \ »убегает от следующего персонажа и предполагает, что все остальные тоже это знают». Для личных проектов это не относится, но в условиях команды это предположение является очень опасным (и потенциально дорогостоящим).
Эдуард Никодей
1
@EduardNicodei О, я согласен. Мы говорили о читателях кода («кто замечает ...?»), А не об авторах. Но также, в некоторых командах можно принять определенный уровень мастерства. Зависит от окружающей среды.
Джонатан Хартли,
5

Я только что обнаружил, что вы также можете использовать "-d ":

cut "-d "

Тест

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
Федорки "ТАК прекратить вредить"
источник
1
Действительно - или '-d '.
mklement0
3
Обратите внимание , что с cut«s перспектива всех следующими одинакова: "-d ", '-d ', -d" ", -d' ', и -d\<space>: все формы непосредственно добавьте аргумент опции (пробел) к опции ( -d) и результату в той же самой строке к тому времени cutих видят: один аргумент, содержащий d, за которым следует пробел, после того как оболочка выполнила удаление кавычек
mklement0
1
@ ответ mklement0 должен быть ответ. Это самый полный на этой странице (хотя это комментарий).
Tresf
@QZSupport: Я ценю чувства и поддержку - это вдохновило меня опубликовать свой собственный ответ с дополнительной справочной информацией.
mklement0
1
Lol захватывающее открытие!
Гарри
4

Вы не можете сделать это легко с помощью cut, если данные имеют, например, несколько пробелов. Я нашел полезным нормализовать ввод для более легкой обработки. Одна хитрость заключается в использовании sed для нормализации, как показано ниже.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
Анси
источник
3

scut , похожая на вырезку утилита (умнее, но медленнее сделанная мной), которая может использовать любое регулярное выражение perl в качестве ломающего токена. Разбивка на пробелах используется по умолчанию, но вы также можете разбивать регулярные выражения с несколькими символами, альтернативные регулярные выражения и т. Д.

scut -f='6 2 8 7' < input.file  > output.file

поэтому приведенная выше команда разбивает столбцы на пробелах и извлекает столбцы (на основе 0) 6 2 8 7 в ​​указанном порядке.

Гарри Мангалам
источник
0

У меня есть ответ (я допускаю несколько запутанный ответ), который включает в себя sed, регулярные выражения и группы захвата:

  • \S* - первое слово
  • \s* - разделитель
  • (\S*) - второе слово - захвачено
  • .* - остальная часть линии

Как sedвыражение, потребность группы захвата экранировать, то есть \(и\) .

В \1возвращает копию захваченной группы, то есть второе слово.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Когда вы смотрите на этот ответ, он несколько сбивает с толку, и, вы можете подумать, зачем беспокоиться? Ну, я надеюсь, что некоторые из них могут пойти "Ага!" и будет использовать этот шаблон для решения некоторых сложных задач извлечения текста с помощью одного sedвыражения.

Стивен Куан
источник