Разделите содержание файла в Linux

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

$ echo a | dd seek=999999999 >sparse
0+1 records in
0+1 records out
2 bytes (2 B) copied, 6.614e-05 s, 30.2 kB/s
$ ls -l a
-rw-r--r-- 1 gilles gilles 511999999490 Apr 30 00:03 sparse
$ du sparse
16      sparse

Файл sparse содержит 511 999 999 490 байтов (999 999 999 блоков 512 байтов, весь нуль, плюс два байта a сопровождаемый новой строкой). Все же общее дисковое пространство, используемое файлом, составляет 16 КБ (4 КБ для заключительного блока и 3 других блоков, содержащих только метаданные, связанные с местоположением других блоков — все они отсутствуют).

Если honey.img образ диска, который был создан достаточно тщательно, это может быть редко, где диск имел неиспользуемое место.

Когда Вы читаете из файла, нет ничего для маркировки его как редкий. Итак, если honey.img большой образ диска, dd может читать гигабайт на гигабайт, содержащий только пустые байты.

Выполнение ls -l и du на файле (или, на OSX, ls -ls) показал бы число байтов и количество блоков, используемых для устройства хранения данных. Если байты не поместились бы в количество блоков, файл редок. Как я пишу, Вы не отправили четкие данные, которые могли подтвердить или ослабить это.

Один инструмент, который я знаю на OSX, который может скопировать редкие файлы эффективно, является rsync. Однако то, что Вы делаете здесь, не копирует файл от одной файловой системы до другого, но копирует поток байтов (который, оказывается, прибывает из файла) на диск. Можно только сделать это, если данные на самом деле соответствуют на целевом диске.

5
06.01.2019, 23:42
5 ответов

Я предполагаю, что этот вопрос связан с тем, корректным?

В этом случае, не был бы, заменяя '^' с новой строкой быть большим количеством ценности Ваш в то время как? В следующем я предполагаю, что Вы имеете в виду '^ ', байт NUL ASCII:

$ sed 's/\o000/\n/g' abc.txt | head -n 2
abc.tar
xxx.tar

Таким образом, Вам нужно

sed 's/\o000/\n/g' abc.txt | head -n 2 > newfile.txt

Объяснение

Это заменяет новой строкой (\n) для каждого байта NUL (\o000) \o часть означает, что то, что следует, является байтом в восьмеричной нотации. Вывод затем передается по каналу к head -n 2 который извлекает первые две строки; и получающиеся строки перенаправляются (>) в файл newfile.txt.

Если для Вас важно, чтобы имена файлов были разделены '^ ', однако, можно использовать это:

perl -nl000 -e '
    $num_lines =2 ;
    push @a,(split /\000/)[0..$num_lines-1];
    print $_ for @a' abc.txt > newfile.txt

Замените значение $num_lines выше по мере необходимости для захвата первого $num_lines строки из файла.

Объяснение

  • -n переключатель говорит perl выполнять код каждой строки входного файла
  • -l000 последовательность говорит perl установить выходной разделитель записей (символ, распечатанный после каждой строки) к байту NUL (000).
  • -e переключатель говорит perl то, что строка, которая следует, является кодом для выполнения.
  • split функционируйте разделяет каждую входную строку с байтом NUL как разделитель, берет первое $num_lines ([0..$num_lines-1]) результаты и помещают их в массив @a. Заметьте, что "текущая входная часть" строки нигде не указана в вызове функции. Это использует то, что скалярная переменная по умолчанию в Perl ($_) параметр по умолчанию split функция (среди других), когда никакой аргумент не предоставляется.
  • Финал foreach цикл печатает каждый элемент в @a (снова отметьте как $_ итератор по умолчанию для foreach цикл). Так как мы установили выходной разделитель записей на восьмеричный 000, мы разделили результаты байтом NUL как прежде.
0
27.01.2020, 20:40
  • 1
    Спасибо @Joseph R, Но можно ли сказать мне, как я могу использовать команду в через Java?? так как я должен передать его в двойных кавычках как "sed 's/\o000/\n/g' abc.txt | главный-n 2> newfile.txt" его ошибка показа для последовательностей. –  Mano 07.08.2013, 08:46
  • 2
    @user1752557, Какие ошибки Вы получаете? –  Joseph R. 07.08.2013, 12:58

Это:

awk -F"@" '{print $1"@"$2"@"}' abc.txt > newfile.txt

достаточно хороший для Вас?

3
27.01.2020, 20:40
  • 1
    Вопрос о записях, разделенных пустыми байтами, не @ персонажи. –  Gilles 'SO- stop being evil' 06.08.2013, 04:22
  • 2
    Копирование моего собственного комментария: В таком случае мой awk идет (я думаю): awk-F" \x00" '{печатают дюйм за 1$ \x00" дюйм за 2$ \x00"}' abc.txt> newfile.txt –  GermanG 06.08.2013, 17:38

Выполнение попытки:

sed -r -i 's/^(.*)@.*@.*$/\1/' file
1
27.01.2020, 20:40
  • 1
    Чему Вы пытаетесь соответствовать (.*)(.*)? Также, почему использование cat? Можно сделать sed -r 'pattern_here' file непосредственно. Наконец, этот код, кажется, предполагает, что входной файл только имеет 3 имен файлов, из которых Вы извлекаете первый только. –  Joseph R. 05.08.2013, 20:37
  • 2
    .* должен соответствовать на чем-либо, идея состоит в том, чтобы разделить контент использования файла @ как разделитель. И почему бы не использовать cat- это - столь же жизнеспособный метод как любой другой. –  Alexej Magura 05.08.2013, 21:14
  • 3
    Моя точка, (.*)(.*) не приведет ни к какому другому результату (.*) почему Вы повторяли его? Что касается, почему бы не использовать cat, это не о функциональности, это о прикреплении на ненужной сложности. Это не что cat был сделан для так или иначе. –  Joseph R. 05.08.2013, 21:17
  • 4
    я думаю, что, возможно, забыл пробовать вышеупомянутое без дополнительного (.*) и так, чтобы может быть то, почему существует дополнительный. При необходимости не стесняйтесь редактировать вышеупомянутое. –  Alexej Magura 05.08.2013, 21:19
  • 5
    Сделанный. Я уезжаю cat до Вашего усмотрения :) –  Joseph R. 05.08.2013, 21:22

Вот пример с помощью Perl:

$ perl -ne '@F = split(/@/,$_); print "$F[1]\@$F[2]@";' abc.txt > newfile.txt

Вышеупомянутое делает следующее:

  • @F = split(/@/,$_) - разделяет содержание файла abc.txt строка за один раз на основе символа @ и хранит получающиеся блоки в массиве (@F).
  • print "$F[1]\@$F[2]@" - печатает первые 2 столбца, (1 и 2), от массива @F и вставляет знак at sign (@) промежуточный каждый столбец.
0
27.01.2020, 20:40

Awk может использовать любой символ в качестве разделителя записей (с новой строкой как значение по умолчанию), за исключением того, что некоторые реализации не поддерживают пустой байт как разделитель. Простофиля (GNU awk), значение по умолчанию awk на самых невстроенных установках Linux, поддержки аннулируют.

gawk -v RS='\0' -v ORS='\0' 'NR <= 2 {print}'

Это может быть сокращено к gawk -v RS='\0' -v ORS='\0' 'NR <= 2' начиная с печати записи действие по умолчанию.

Для большого файла необходимо выйти после второй строки.

gawk -v RS='\0' -v ORS='\0' 'NR==3 {exit} {print}'

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

tr '\0\n' '\n\0' | head -n 2 | tr '\0\n' '\n\0'
0
27.01.2020, 20:40

Теги

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