4. Основное и практическое использование команды Cut в Linux
Команда Cut в Linux позволяет удалять данные в каждой строке файла. Прочтите это руководство, чтобы узнать, как эффективно использовать его для обработки текста или файла данных CSV.
Команда вырезания — это канонический инструмент для удаления «столбцов» из текстового файла. В этом контексте «столбец» можно определить как диапазон символов или байтов, идентифицируемых по их физическому положению в строке, или диапазон полей, разделенных разделителем.
Я писал об использовании команд AWK ранее. В этом подробном руководстве я объясню четыре основных и практических примера команды Cut в Linux, которые вам очень помогут.
4 практических примера команды Cut в Linux
Если хотите, вы можете посмотреть это видео, в котором объясняются те же практические примеры команды вырезания, которые я перечислил в статье.
1. Работа с диапазонами символов
При вызове с параметром командной строки -c
команда вырезания удалит диапазоны символов.
Как и любой другой фильтр, команда вырезания не меняет входной файл, а копирует измененные данные в стандартный вывод. Вы несете ответственность за перенаправление вывода команды в файл для сохранения результата или за использование канала для отправки его в качестве входных данных для другой команды.
Если вы загрузили образцы тестовых файлов, использованных в видео выше, вы можете увидеть файл данных BALANCE.txt
, полученный прямо из бухгалтерской программы, которую моя жена использует на работе:
sh$ head BALANCE.txt
ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
4 1012017 623477 TIDE SCHEDULE ALNEENRE-4701-LOC 00000001615,00
4 1012017 445452 VAT BS/ENC ALNEENRE-4701-LOC 00000000323,00
4 1012017 4356 PAYABLES ALNEENRE-4701-LOC 00000001938,00
5 1012017 623372 ACCOMODATION GUIDE ALNEENRE-4771-LOC 00000001333,00
5 1012017 445452 VAT BS/ENC ALNEENRE-4771-LOC 00000000266,60
5 1012017 4356 PAYABLES ALNEENRE-4771-LOC 00000001599,60
6 1012017 4356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
6 1012017 445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
6 1012017 623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00
Это текстовый файл фиксированной ширины, поскольку поля данных дополняются переменным количеством пробелов, чтобы обеспечить их отображение в виде хорошо выровненной таблицы.
Как следствие, столбец данных всегда начинается и заканчивается в одной и той же позиции символа в каждой строке. Однако есть небольшая ловушка: несмотря на свое название, команда cut
на самом деле требует от вас указать диапазон данных, которые вы хотите сохранить, а не диапазон, который вы хотите удалить. Итак, если мне нужны только столбцы ACCOUNTNUM
и ACCOUNTLIB
в файле данных выше, я бы написал следующее:
sh$ cut -c 25-59 BALANCE.txt | head
ACCOUNTNUM ACCOUNTLIB
623477 TIDE SCHEDULE
445452 VAT BS/ENC
4356 /accountPAYABLES
623372 ACCOMODATION GUIDE
445452 VAT BS/ENC
4356 PAYABLES
4356 PAYABLES
445452 VAT BS/ENC
623795 TOURIST GUIDE BOOK
Что такое диапазон?
Как мы только что видели, команда вырезания требует, чтобы мы указали диапазон данных, которые мы хотим сохранить. Итак, давайте более формально представим, что такое диапазон: для команды cut
диапазон определяется начальной и конечной позициями, разделенными дефисом. Диапазоны отсчитываются от 1, то есть первый элемент строки имеет номер 1, а не 0. Диапазоны являются инклюзивными: начало и конец будут сохранены в выводе, а также все символы между ними. Ошибочно указывать диапазон, конечная позиция которого находится раньше («ниже») его начальной позиции. В качестве сокращения можно опустить начальное или конечное значение, как описано в таблице ниже:
a-b
: диапазон между a и b (включительно).a
: эквивалент диапазонаa-a
-b
: эквивалент1-a
b-
: эквивалентb-∞
Команды вырезания позволяют указать несколько диапазонов, разделив их запятой. Вот несколько примеров:
# Keep characters from 1 to 24 (inclusive)
cut -c -24 BALANCE.txt
# Keep characters from 1 to 24 and 36 to 59 (inclusive)
cut -c -24,36-59 BALANCE.txt
# Keep characters from 1 to 24, 36 to 59 and 93 to the end of the line (inclusive)
cut -c -24,36-59,93- BALANCE.txt
Одним из ограничений (или особенностей, в зависимости от того, как вы это видите) команды cut
является то, что она никогда не меняет порядок данных. Таким образом, следующая команда выдаст точно такой же результат, как и предыдущая, несмотря на то, что диапазоны указаны в другом порядке:
cut -c 93-,-24,36-59 BALANCE.txt
Вы можете легко это проверить с помощью команды diff
:
diff -s <(cut -c -24,36-59,93- BALANCE.txt) \
<(cut -c 93-,-24,36-59 BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical
Аналогично, команда cut
никогда не дублирует данные:
# One might expect that could be a way to repeat
# the first column three times, but no...
cut -c -10,-10,-10 BALANCE.txt | head -5
ACCDOC
4
4
4
5
Стоит упомянуть, что было предложено использовать опцию -o
, чтобы снять эти два последних ограничения, позволяя утилите cut
изменять порядок или дублировать данные. Но это было отклонено комитетом POSIX«поскольку этот тип усовершенствования выходит за рамки проекта стандарта IEEE P1003.2b. ”
Лично я не знаю ни одной урезанной версии, реализующей это предложение в качестве расширения. Но если да, пожалуйста, поделитесь этим с нами в разделе комментариев!
2. Работа с диапазонами байтов
При вызове с параметром командной строки -b
команда вырезания удалит диапазоны байт.
На первый взгляд нет очевидной разницы между диапазонами символов и байтов:
sh$ diff -s <(cut -b -24,36-59,93- BALANCE.txt) \
<(cut -c -24,36-59,93- BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical
Это потому, что мой пример файла данных использует кодировку символов US-ASCII («charset»), поскольку команда file -i
может правильно ее угадать:
sh$ file -i BALANCE.txt
BALANCE.txt: text/plain; charset=us-ascii
В этой кодировке символов существует взаимно однозначное соответствие между символами и байтами. Используя только один байт, вы теоретически можете закодировать до 256 различных символов (цифр, букв, знаков препинания, символов и т. д.). На практике это число намного меньше, поскольку кодировки символов предусматривают некоторые специальные значения (например, 32 или 65 управляющих символов). обычно встречается). В любом случае, даже если бы мы могли использовать весь диапазон байтов, этого было бы далеко недостаточно для хранения разнообразия человеческого письма. Итак, сегодня взаимно однозначное сопоставление символов и байтов является скорее исключением, чем нормой, и почти всегда заменяется повсеместной многобайтовой кодировкой UTF-8. Давайте теперь посмотрим, как с этим справится команда Cut.
Работа с многобайтовыми символами
Как я уже говорил ранее, образцы файлов данных, использованные в качестве примеров для этой статьи, взяты из бухгалтерского программного обеспечения, которым пользовалась моя жена. В нем добавлено, что она недавно обновила это программное обеспечение, и после этого экспортированные текстовые файлы немного отличались. Предлагаю вам попробовать заметить разницу самостоятельно:
sh$ head BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
4 1012017 623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
4 1012017 445452 VAT BS/ENC ALNÉENRE-4701-LOC 00000000323,00
4 1012017 4356 PAYABLES ALNÉENRE-4701-LOC 00000001938,00
5 1012017 623372 ACCOMODATION GUIDE ALNÉENRE-4771-LOC 00000001333,00
5 1012017 445452 VAT BS/ENC ALNÉENRE-4771-LOC 00000000266,60
5 1012017 4356 PAYABLES ALNÉENRE-4771-LOC 00000001599,60
6 1012017 4356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
6 1012017 445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
6 1012017 623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00
Название этого раздела может помочь вам понять, что изменилось. Но независимо от того, найдено оно или нет, давайте посмотрим теперь на последствия этого изменения:
sh$ cut -c 93-,-24,36-59 BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
Я скопировал выше вывод команды in-extenso, поэтому должно быть очевидно, что с выравниванием столбцов что-то пошло не так.
Объяснение заключается в том, что исходный файл данных содержал только символы US-ASCII (символы, знаки препинания, цифры и латинские буквы без каких-либо диакритических знаков).
Но если вы внимательно посмотрите на файл, созданный после обновления программного обеспечения, вы увидите, что в новом файле данных экспорта теперь сохраняются буквы с диакритическими знаками. Например, компания под названием «ALNÉENRE» теперь пишется правильно, тогда как ранее она экспортировалась как «ALNEENRE» (без акцента).
Утилита file -i
не пропустила это изменение, поскольку теперь сообщает, что файл имеет кодировку UTF-8:
sh$ file -i BALANCE-V2.txt
BALANCE-V2.txt: text/plain; charset=utf-8
Чтобы увидеть, как закодированы буквы с диакритическими знаками в файле UTF-8, мы можем использовать утилиту hexdump
, которая позволяет нам просматривать непосредственно байты в файле:
# To reduce clutter, let's focus only on the second line of the file
sh$ sed '2!d' BALANCE-V2.txt
4 1012017 623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
sh$ sed '2!d' BALANCE-V2.txt | hexdump -C
00000000 34 20 20 20 20 20 20 20 20 20 31 30 31 32 30 31 |4 101201|
00000010 37 20 20 20 20 20 20 20 36 32 33 34 37 37 20 20 |7 623477 |
00000020 20 20 20 54 49 44 45 20 53 43 48 45 44 55 4c 45 | TIDE SCHEDULE|
00000030 20 20 20 20 20 20 20 20 20 20 20 41 4c 4e c3 89 | ALN..|
00000040 45 4e 52 45 2d 34 37 30 31 2d 4c 4f 43 20 20 20 |ENRE-4701-LOC |
00000050 20 20 20 20 20 20 20 20 20 20 20 20 20 30 30 30 | 000|
00000060 30 30 30 30 31 36 31 35 2c 30 30 20 20 20 20 20 |00001615,00 |
00000070 20 20 20 20 20 20 20 20 20 20 20 0a | .|
0000007c
В строке 00000030 вывода hexdump
после нескольких пробелов (байт 20
) вы можете увидеть:
буква
A
кодируется как байт41
,буква
L
кодируется байтом4c
,а буква
N
кодируется как байт4e
.
Но заглавная ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА E С ОСТРЫМ (так как это официальное название буквы É в стандарте Unicode) кодируется с помощью два байта c3 89
И вот в чем проблема: использование команды cut
с диапазонами, выраженными в виде позиций байтов, хорошо работает для кодировок фиксированной длины, но не для кодировок переменной длины, таких как UTF-8 или Shift JIS. Это ясно объяснено в следующем ненормативном отрывке из стандарта POSIX:
Более ранние версии утилиты Cut работали в среде, где байты и символы считались эквивалентными (в некоторых реализациях обработка по модулю
и <tab>). В расширенный мир многобайтовых символов добавлена новая опция -b.
Эй, подожди минутку! В приведенном выше «неисправном» примере я использовал не опцию -b
, а опцию -c
. Итак, не должно ли сработать?!?
Да, должно: к сожалению, мы живем в 2018 году, и, несмотря на это, начиная с GNU Coreutils 8.30, реализация GNU утилиты Cut по-прежнему не обрабатывает несколько -байтовые символы правильно. Цитируя документацию GNU, опция -c
выглядит следующим образом: “То же самое, что и -b, но интернационализация изменит это[… ] ” — упоминание, существующее уже более 10 лет!
С другой стороны, реализация утилиты Cut в OpenBSD совместима с POSIX и будет учитывать текущие настройки локали для правильной обработки многобайтовых символов:
# Ensure subseauent commands will know we are using UTF-8 encoded
# text files
openbsd-6.3$ export LC_CTYPE=en_US.UTF-8
# With the `-c` option, cut works properly with multi-byte characters
openbsd-6.3$ cut -c -24,36-59,93- BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
Как и ожидалось, при использовании байтового режима -b
вместо символьного режима -c
реализация вырезания OpenBSD ведет себя как устаревший cut
:
openbsd-6.3$ cut -b -24,36-59,93- BALANCE-V2.txt
ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
4 1012017 TIDE SCHEDULE 00000001615,00
4 1012017 VAT BS/ENC 00000000323,00
4 1012017 PAYABLES 00000001938,00
5 1012017 ACCOMODATION GUIDE 00000001333,00
5 1012017 VAT BS/ENC 00000000266,60
5 1012017 PAYABLES 00000001599,60
6 1012017 PAYABLES 00000001837,20
6 1012017 VAT BS/ENC 00000000306,20
6 1012017 TOURIST GUIDE BOOK 00000001531,00
19 1012017 SEMINAR FEES 00000000080,00
19 1012017 PAYABLES 00000000080,00
28 1012017 MAINTENANCE 00000000746,58
28 1012017 VAT BS/ENC 00000000149,32
28 1012017 PAYABLES 00000000895,90
31 1012017 PAYABLES 00000000240,00
31 1012017 VAT BS/DEBIT 00000000040,00
31 1012017 ADVERTISEMENTS 00000000200,00
32 1012017 WATER 00000000202,20
32 1012017 VAT BS/DEBIT 00000000020,22
32 1012017 WATER 00000000170,24
32 1012017 VAT BS/DEBIT 00000000009,37
32 1012017 PAYABLES 00000000402,03
34 1012017 RENTAL COSTS 00000000018,00
34 1012017 PAYABLES 00000000018,00
35 1012017 MISCELLANEOUS CHARGES 00000000015,00
35 1012017 VAT BS/DEBIT 00000000003,00
35 1012017 PAYABLES 00000000018,00
36 1012017 LANDLINE TELEPHONE 00000000069,14
36 1012017 VAT BS/ENC 00000000013,83
3. Работа с полями
В некотором смысле работать с полями в текстовом файле с разделителями проще с помощью утилиты cut
, поскольку ей нужно будет только найти разделители полей (один байт) в каждой строке, скопировав, а затем дословно воспроизведя содержимое поля. на вывод, не беспокоясь о каких-либо проблемах с кодированием.
Вот пример текстового файла с разделителями:
sh$ head BALANCE.csv
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;ACCDOCLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;ALNEENRE-4701-LOC;00000001615,00;
4;1012017;445452;VAT BS/ENC;ALNEENRE-4701-LOC;00000000323,00;
4;1012017;4356;PAYABLES;ALNEENRE-4701-LOC;;00000001938,00
5;1012017;623372;ACCOMODATION GUIDE;ALNEENRE-4771-LOC;00000001333,00;
5;1012017;445452;VAT BS/ENC;ALNEENRE-4771-LOC;00000000266,60;
5;1012017;4356;PAYABLES;ALNEENRE-4771-LOC;;00000001599,60
6;1012017;4356;PAYABLES;FACT FA00006253 - BIT QUIROBEN;;00000001837,20
6;1012017;445452;VAT BS/ENC;FACT FA00006253 - BIT QUIROBEN;00000000306,20;
6;1012017;623795;TOURIST GUIDE BOOK;FACT FA00006253 - BIT QUIROBEN;00000001531,00;
Возможно, вам известен этот формат файла как CSV (значения, разделенные запятыми), даже если разделителем полей не всегда является запятая. Например, точка с запятой (;
) часто используется в качестве разделителя полей и часто является выбором по умолчанию при экспорте данных в формате «CSV» в странах, где уже используется запятая в качестве десятичного разделителя ( как мы делаем во Франции — отсюда и выбор этого персонажа в моем файле-примере). Другой популярный вариант использует символ табуляции в качестве разделителя полей, создавая то, что иногда называют файлом значений, разделенных табуляцией. Наконец, в мире Unix и Linux двоеточие (:
) является еще одним относительно распространенным разделителем полей, который вы можете встретить, например, в стандартных /etc/passwd
и файлы /etc/group
.
При использовании формата текстового файла с разделителями вы предоставляете команде вырезания диапазон полей, которые необходимо сохранить, используя параметр -f
, и вам необходимо указать разделитель с помощью -d
(без параметра -d
утилита вырезания по умолчанию использует символ табуляции в качестве разделителя):
sh$ cut -f 5- -d';' BALANCE.csv | head
ACCDOCLIB;DEBIT;CREDIT
ALNEENRE-4701-LOC;00000001615,00;
ALNEENRE-4701-LOC;00000000323,00;
ALNEENRE-4701-LOC;;00000001938,00
ALNEENRE-4771-LOC;00000001333,00;
ALNEENRE-4771-LOC;00000000266,60;
ALNEENRE-4771-LOC;;00000001599,60
FACT FA00006253 - BIT QUIROBEN;;00000001837,20
FACT FA00006253 - BIT QUIROBEN;00000000306,20;
FACT FA00006253 - BIT QUIROBEN;00000001531,00;
Обработка строк, не содержащих разделитель
Но что, если какая-то строка входного файла не содержит разделителя? Заманчиво представить это как строку, содержащую только первое поле. Но это не то, что делает утилита Cut.
По умолчанию при использовании опции -f
утилита вырезания всегда дословно выводит строку, не содержащую разделитель (вероятно, предполагая, что это строка, не содержащая данных, например, заголовок или какой-то комментарий). ):
sh$ (echo "# 2018-03 BALANCE"; cat BALANCE.csv) > BALANCE-WITH-HEADER.csv
sh$ cut -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
# 2018-03 BALANCE
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00
Используя опцию -s
, вы можете изменить это поведение, поэтому cut
всегда будет игнорировать такую строку:
sh$ cut -s -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00
00000001333,00;
Если у вас хакерское настроение, вы можете использовать эту функцию как относительно неясный способ сохранять только строки, содержащие заданный символ:
# Keep lines containing a `e`
sh$ printf "%s\n" {mighty,bold,great}-{condor,monkey,bear} | cut -s -f 1- -d'e'
Изменение выходного разделителя
В качестве расширения реализация Cut в GNU позволяет использовать другой разделитель полей для вывода с помощью опции --output-delimiter
:
sh$ cut -f 5,6- -d';' --output-delimiter="*" BALANCE.csv | head
ACCDOCLIB*DEBIT*CREDIT
ALNEENRE-4701-LOC*00000001615,00*
ALNEENRE-4701-LOC*00000000323,00*
ALNEENRE-4701-LOC**00000001938,00
ALNEENRE-4771-LOC*00000001333,00*
ALNEENRE-4771-LOC*00000000266,60*
ALNEENRE-4771-LOC**00000001599,60
FACT FA00006253 - BIT QUIROBEN**00000001837,20
FACT FA00006253 - BIT QUIROBEN*00000000306,20*
FACT FA00006253 - BIT QUIROBEN*00000001531,00*
Обратите внимание: в этом случае заменяются все вхождения разделителя полей, а не только те, которые находятся на границе диапазонов, указанных в аргументах командной строки.
4. Расширения GNU, не относящиеся к POSIX.
Говоря о расширениях GNU, не относящихся к POSIX, пара из них может оказаться особенно полезной. Стоит отметить, что следующие расширения одинаково хорошо работают с байтовыми, символьными (что это означает в текущей реализации GNU) или диапазонами полей:--complement
Думайте об этом параметре как о восклицательном знаке в адресе sed (!
); вместо того, чтобы сохранять данные в соответствии с заданным диапазоном, cut
будет сохранять данные, НЕ соответствующие диапазону
# Keep only field 5
sh$ cut -f 5 -d';' BALANCE.csv |head -3
ACCDOCLIB
ALNEENRE-4701-LOC
ALNEENRE-4701-LOC
# Keep all but field 5
sh$ cut --complement -f 5 -d';' BALANCE.csv |head -3
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;00000001615,00;
4;1012017;445452;VAT BS/ENC;00000000323,00;
--оканчивается нулем
(-z
)
используйте символ NUL в качестве признака конца строки вместо символа новой строки. Опция -z
особенно полезна, когда ваши данные могут содержать встроенные символы новой строки, например, при работе с именами файлов (поскольку новая строка является допустимым символом в имени файла, а NUL — нет).
Чтобы показать вам, как работает опция -z
, давайте проведем небольшой эксперимент. Сначала мы создадим файл, имя которого будет содержать вставленные новые строки:
bash$ touch
Давайте теперь предположим, что я хочу отобразить первые 5 символов каждого имени файла *.txt
. Наивное решение здесь с треском провалится:
sh$ ls -1 *.txt | cut -c 1-5
BALAN
BALAN
EMPTY
FILE
WITH
NAME.
Возможно, вы уже читали, что ls
был разработан для использования человеком, и его использование в командном конвейере является антишаблоном (это действительно так). Поэтому давайте вместо этого воспользуемся командой find:
sh$ find . -name '*.txt' -printf "%f\n" | cut -c 1-5
BALAN
EMPTY
FILE
WITH
NAME.
BALAN
и… это привело, по сути, к тому же ошибочному результату, что и раньше (хотя и в другом порядке, поскольку ls
неявно сортирует имена файлов, чего не делает команда find
).
Проблема в том, что в обоих случаях команда cut
не может отличить символ новой строки, являющийся частью поля данных (имени файла), и символ новой строки, используемый в качестве маркера конца записи. Но использование нулевого байта (\0
) в качестве признака конца строки устраняет путаницу, и мы наконец можем получить ожидаемый результат:
# I was told (?) some old versions of tr require using \000 instead of \0
# to denote the NUL character (let me know if you needed that change!)
sh$ find . -name '*.txt' -printf "%f\0" | cut -z -c 1-5| tr '\0' '\n'
BALAN
EMPTY
BALAN
В этом последнем примере мы отходим от сути этой статьи — команды cut
. Итак, я позволю вам попытаться самостоятельно понять значение необычного "%f\0"
после аргумента printf команды find или почему я использовал команду tr в конце конвейера. .
С помощью команды «Вырезать» можно сделать гораздо больше.
Я только что показал наиболее распространенное и, на мой взгляд, самое важное использование команды «Вырезать». Вы можете применить команду еще более практичными способами. Это зависит от вашего логического рассуждения и воображения.
Не стесняйтесь использовать раздел комментариев ниже, чтобы опубликовать свои выводы. И, как всегда, если вам понравилась эта статья, не забудьте поделиться ею на своих любимых сайтах и в социальных сетях!