Поиск…


Вступление

Команда cut - это быстрый способ извлечения частей строк текстовых файлов. Он относится к самым старым командам Unix. Его наиболее популярными реализациями является версия GNU, найденная в Linux, и версия FreeBSD, найденная на MacOS, но каждый аромат Unix имеет свои собственные. См. Ниже различия. Строки ввода считываются либо из stdin либо из файлов, перечисленных в качестве аргументов в командной строке.

Синтаксис

  • cut -f1,3 # извлечь первое и третье поля с разделителями табуляции (из stdin)

  • cut -f1-3 # экстракт от первого до третьего поля (в конце включены)

  • cut -f-3 # -3 интерпретируется как 1-3

  • cut -f2- # 2- интерпретируется как от второго до последнего

  • cut -c1-5,10 # extract from stdin символы в позициях 1,2,3,4,5,10

  • cut -s -f1 # подавлять строки, не содержащие разделителей

  • cut --complement -f3 # (только разрезание GNU) извлекает все поля, кроме третьего

параметры

параметр подробности
-f, --fields Выбор на местах
-d, --delimiter Разделитель для выбора на местах
-c, --characters Выбор на основе символов, игнорируемый разделитель или ошибка
-s, - только разграниченные Удерживать строки без разделительных символов (напечатано как - иначе)
--complement Перевернутый выбор (извлекать все, кроме указанных полей / символов
--output-разделитель Укажите, когда он должен отличаться от входного разделителя

замечания

1. Синтаксические различия

Длинные параметры в приведенной выше таблице поддерживаются только версией GNU.

2. Персонаж не получает специального лечения

Например, FreeBSD cut (который поставляется с MacOS) не имеет ключа --complement , а в случае диапазонов colrm вместо него можно использовать команду colrm :

  $ cut --complement -c3-5 <<<"123456789"
  126789

  $ colrm 3 5 <<<"123456789"
  126789

Однако существует большая разница, поскольку colrm обрабатывает символы TAB (ASCII 9) как реальные таблицы до следующего кратного восьми, а обратные пространства (ASCII 8) равны -1; напротив, cut обрабатывает всех персонажей как одну ширину столбца.

  $ colrm  3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
  12ABCDEF

  $ cut --complement -c3-8 <<<$'12\tABCDEF'
  12F

3. (Все еще нет) Интернационализация

Когда был разработан cut , все символы были одним байтом, а интернационализация не была проблемой. При написании систем с более широкими символами стало популярным решение, принятое POSIX, заключалось в том, чтобы подгонять между старым ключом -c , который должен сохранять смысл выбора символов, независимо от того, сколько байтов в ширину, и ввести новый переключатель -b который должен выберите байты, независимо от текущей кодировки символов. В большинстве популярных реализаций -b был введен и работает, но -c все еще работает точно так же, как -b но не так, как должно. Например, при cut GNU:

Кажется, что спам-фильтр SE черным списком английских текстов с изолированными иероглифами кандзи в них. Я не мог преодолеть это ограничение, поэтому следующие примеры менее выразительны, чем могли бы быть.

  # In an encoding where each character in the input string is three bytes wide,
  # Selecting bytes 1-6 yields the first two characters (correct)
  $ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
  ...first two characters of each line...
  

  # Selecting all three characters with the -c switch doesn’t work.
  # It behaves like -b, contrary to documentation.
  $ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
  ...first character of each line...

  # In this case, an illegal UTF-8 string is produced.
  # The -n switch would prevent this, if implemented.
  $ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
  ...second byte, which is an illegal UTF-8 sequence...

Если ваши символы находятся за пределами диапазона ASCII, и вы хотите использовать cut , вы всегда должны знать ширину символов в кодировке и использовать -b соответственно. Если и когда -c начинает работать как задокументированный, вам не придется менять свои скрипты.

4. Сравнение скорости

cut ограничения «s есть люди , сомневающихся свою полезность. Фактически, та же функциональность может быть достигнута благодаря более мощным, более популярным утилитам. Однако преимуществом cut является его производительность . Ниже приведены некоторые сравнения скорости. test.txt имеет три миллиона строк с пятью полями, разделенными пробелами. Для awk теста использовался mawk , потому что он быстрее, чем GNU awk . Сама оболочка (последняя строка) является наихудшим исполнителем. Временные значения (в секундах) - это то, что команда time дает как реальное время .

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

команда Время
cut -d ' ' -f1,2 test.txt 1.138s
awk '{print $1 $2}' test.txt 1.688s
join -a1 -o1.1,1.2 test.txt /dev/null 1.767s
perl -lane 'print "@F[1,2]"' test.txt 11.390s
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt 22.925s
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt 52.122s
while read ab _; do echo $a $b; done <test.txt 55.582s

5. Справочные справочные страницы

Основное использование

Типичное использование файлов CSV-типа, где каждая строка состоит из полей, разделенных разделителем, указанным опцией -d . Разделителем по умолчанию является символ TAB. Предположим, у вас есть файл данных data.txt с такими строками, как

0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367

затем

# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644

# extract the second dot-delimited field
$ cut -d. -f2 data.txt    
8024
3205
2367

# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt 
948.80
056222    
943831

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

GNU cut позволяет указать параметр --output-delimiter : (независимая функция этого примера заключается в том, что точку с запятой в качестве входного разделителя необходимо экранировать, чтобы избежать его специальной обработки оболочкой)

$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b

Только один разделитель

У вас не может быть более одного разделителя: если вы укажете что-то вроде -d ",;:" , некоторые реализации будут использовать только первый символ в качестве разделителя (в данном случае - запятую). Другие реализации (например, GNU cut ) будут давать вы получите сообщение об ошибке.

$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.

Повторные разделители интерпретируются как пустые поля

$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b

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

$ cut -d ' ' -f1,3 <<<"a  b c d e"
a b

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

Нет цитирования

Невозможно защитить разделитель. Таблицы и аналогичное программное обеспечение для обработки CSV обычно могут распознавать символ цитирования текста, который позволяет определять строки, содержащие разделитель. С cut вы не можете.

$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1

Извлечение, а не манипулирование

Вы можете извлекать только части строк, а не изменять порядок или повторять поля.

$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow