команда sort добавляет/удаляет данные по желанию

С помощьюawk-я чувствую, что это можно упростить, но пока не могу

awk '/uid=/ && p~/uid=/{c=4; next}
     !(c && c--) && NR>1{print p} {p=$0}
     END{if(c==0)print p}' ip.txt
  • по умолчанию неинициализированные переменные в awk будут пустой строкой или 0 в зависимости от контекста
  • /uid=/ && p~/uid=/, если текущая и предыдущая строки содержат uid=
    • c=4; nextинициализировать cколичеством строк для пропуска (плюс 1 из-за логики, которую я закончил с ). Кроме того, пропустите остальную часть кода
  • !(c && c--) && NR>1{print p}вывести предыдущую строку, если номер текущей строки больше 1 и если c==0. Если cбольше, чем 0, оно будет продолжать уменьшаться до c==0
  • .
  • {p=$0}сохранить предыдущую строку для дальнейшего использования
  • END{if(c==0)print p}напечатать последнюю строку, еслиc==0
6
22.05.2020, 13:19
1 ответ

Здесь происходят две вещи, и они несколько противоречат друг другу.

  1. Входной файл кодируется непоследовательно и преобразуется с помощью sortв действительный формат UTF -8. Это делает файл больше . Это влияет на сообщаемый размер ls -l-.
  2. Что-то странное происходит с хранилищем файловой системы, которое изменяет количество блоков, используемых файлами одинакового -размера, в зависимости от того, как они создаются. Это влияет на сообщаемый размерdu -shk-и в основном делает его меньше (, но может быть и так ).

Я могу дать более точное объяснение первому пункту, чем второму.хотя краткий ответ заключается в том, что duне является подходящим инструментом для измерения размеров отдельных файлов, особенно в APFS.

В следующих двух разделах подробно рассматриваются оба фактора.


Для коэффициента (1 )файл содержит строки, не закодированные в кодировке UTF -8, которая является кодировкой локали по умолчанию в macOS. Команда sortизменяет эти плохо -закодированные строки при их выводе, увеличивая размер файла . Мы рассмотрим это ниже, но это краткий ответ, и вы можете перейти к следующему разделу, если этого достаточно.

Если мы отсортируем предоставленный файл в локали C, а затем снова в локали en _US.UTF -8, два файла будут иметь разные фактические размеры:

139921497 rockyou.txt
139921497 rockyou_c.txt
139921847 rockyou_sorted.txt

Первое различие между отсортированными файлами C -и UTF -8 -заключается в

299c299
<  �R3CKL3$$�
---
>  R3CKL3$$

Первая строка содержит байты 0x93 и 0x94 в начале и в конце пароля, которые не являются допустимыми автономными байтами в UTF -8 (они могут отображаться только как байты продолжения многобайтового -символа ). Второй содержит кодовые точки Unicode U+0093 и U+0094, закодированные как два байта UTF -8 каждый, C2 93и C2 94.

В результате исходная строка из десяти -байтов записывается как строка из двенадцати -байтов . Во всем файле эти изменения добавляют до 350 дополнительных байтов в отсортированном файле по сравнению с исходным.

Я считаю, что здесь произошло:

  1. Исходная строка была“R3CKL3$$”(включена в кавычки ), закодирована в кодовой странице Windows -1252(cp1252 ). Парные кавычки 0x93 и 0x94 в этой кодировке.
  2. Он был добавлен в эту коллекцию как необработанные байты без учета кодировки, как и многие другие записи.
  3. В истинной латинице -1 ISO 8859 -1 диапазон байтов 0x80 -0x9f не занят,но в ISO -8859 -1 (обратите внимание на дополнительный дефис )он заполняется управляющими символами C1 .
  4. Весь ISO -8859 -1 кодируется как блок «Latin -1 Supplement » в Unicode, с кодовыми точками, соответствующими необработанным значениям байтов и представленным несколькими -байтовые кодировки с C2 80по C2 BFи с C3 80по C3 BFв UTF -8 .
  5. Сортировка macOS интерпретирует одиночные байты продолжения как попытку ISO -8859 -1 и внутренне преобразует их в строки Unicode таким образом для сортировки :байт 0x93 становится U+0093 в строке, которая отсортировано.
  6. Эти переведенные строки выводятся в UTF -8 вместо исходных строк из файла.

Другие вопросы на сайте обсуждают, как исправить неправильно закодированный файл cp1252 постфактум, если вам это нужно.

POSIX отмечает, что в случае, если строки содержат последовательности байтов, которые не образуют допустимые символы в локали, поведение утилиты не определено, поэтому это строго разрешено стандартом и не ошибка соответствия. Это по меньшей мере неожиданно и, возможно, поведенческая ошибка. Другие реализации, которые я пробовал, не ведут себя таким образом.

Этот фактор подталкивает к тому, чтобы файл стал немного больше при сортировке, и по-настоящему больше -при чтении из файла вы получите больше байтов.


Фактор (2 )в целом подталкивает к тому, чтобы файл стал "меньше", но это своего рода иллюзия. Чтение файла не обязательно приведет к увеличению или уменьшению байтов только потому, что duговорит, что они имеют разные размеры.

du -shk, как правило, не является подходящим способом проверки размеров файлов,потому что

The du utility displays the file system block usage for each file argument

Это означает, что он сообщает информацию о том, сколько физического пространства занимает файл, а не о его логическом размере. В зависимости от точных параметров файловой системы и рассматриваемых файлов количество блоков может сильно отличаться от ожидаемого. Есть случаев, когда подсчет блоков полезен, например, когда вы сжимаете файлы на полное устройство, но не обычно.

Одной из причин, по которой счетчики блоков сегодня еще менее полезны, является то, что современные файловые системы не всегда записывают данные точно так, как они заданы:например, они могут молча сжимать их перед сохранением в большей или меньшей степени, требуя меньше блоки или оставляйте пустое пространство внутри блоков, чтобы упростить вставку в будущем, используя больше блоков. Разреженные файлы пропускают блоки нулей, но дедупликация может пойти еще дальше.

В случае с APFS поддерживается сжатие с использованием нескольких алгоритмов, некоторые виды дедупликации и дельта-кодирования, шифрование и расширенные метаданные. Некоторые или все из них могут быть задействованы, наиболее вероятные различия в прозрачном сжатии при записи файла, в зависимости от реализации приложения и загрузки системы.

Если мы просто catфайл несколько раз, мы уже можем увидеть различия. Если я скачал rockyou.txtс curl -O, то:

  • cat rockyou.txt > rockyou2.txtсоздает файл с тем же количеством байтов (139921497 ), но с другим количеством блоков для меня (147504 дляcurl-создал один против 147460 для cat's)
  • Поиск нового файла снова дает мне еще один счетчик блоков (147520 ), как иcp(150512 ).
  • Повторный запуск обеих строк дает другие результаты, отличные от первой попытки.

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


В целом, у нас есть проблема с кодировкой, из-за которой файл действительно становится немного больше , что уравновешивается поведением файловой системы, которое слегка изменяет сообщаемое количество блоковэтого большего файла, что делает это меньше в вашем тесте. Измерение истинного размера показывает последовательное увеличение на 350 байт при сортировке. В зависимости от того, как вы на это смотрите, это может быть ошибка в сортировке, или это может быть ошибка в использовании сортировки, давая ему плохой файл.

4
28.04.2021, 23:13

Теги

Похожие вопросы