Дополнительно
Инструмент Bash для получения n-ой строки из файла
Есть ли "канонический" способ сделать это? Я использую head -n | tail -1
, что делает трюк, но мне стало интересно, есть ли в Bash инструмент, который специально извлекает строку (или диапазон строк) из файла.
Под "каноническим" я имею в виду программу, основная функция которой заключается в этом.
535
18
head
и pipe сtail
будет медленным для огромного файла. Я бы предложил использоватьed
следующим образом:Где
NUM
- номер строки, которую вы хотите вывести; так, например,sed '10q;d' file
выведет 10-ю строкуfile
.Объяснение:
NUMq
немедленно завершит работу, когда номер строки будет равенNUM
.d
удалит строку вместо ее печати; это запрещено на последней строке, потому чтоq
заставляет пропустить остальную часть сценария при выходе.Если у вас есть
NUM
в переменной, вы захотите использовать двойные кавычки вместо одинарных:выведет вторую строку
2011-я строка
строка 10 до строки 33
1-я и 3-я строки
и так далее...
Для добавления строк с помощью sed, вы можете проверить это:
https://stackoverflow.com/q/15555781/#16246806
У меня уникальная ситуация, когда можно тест решения, предложенные на данной странице, и поэтому я'м пишу этот ответ как консолидация предлагаемого решения с включенными раз для каждого.
Настройка
У меня 3.261 гигабайт текстовых данных файл с одну пару ключ-значение для каждой строки. Файл содержит 3,339,550,320 строк в целом и не поддается открытию в любом редакторе я пробовал, в том числе и мой ВИМ. Мне нужно, чтобы подмножество этого файла, чтобы исследовать некоторые из тех ценностей, которые я've обнаружил только начальную строку ~500,000,000.
Поскольку файл имеет очень много строк:
Мои сценарии-это решение, которое извлекает только одну строку из файла без чтения любой другой строке в файле, но я могу'т думаю, что я бы сделать это в bash.
Для целей моей вменяемости я'м не собираюсь быть пытаясь прочитать полный 500,000,000 линий Я'd нужен для моей проблемы. Вместо этого я'll быть пытаясь извлечь строку 50,000,000 из 3,339,550,320 (что означает, прочитав полный файл займет 60х дольше, чем это необходимо).
Я буду использовать "время" в ориентир каждой команды.
Базовый
Сначала позвольте's смотреть, как "голова ""хвост" решение:
Исходные данные для строки 50 млн. 00:01:15.321, если я'd и пошли прямо по строке 500 млн. Это'd и, наверное, ~12,5 минут.
вырезать
Я'м сомнительный, но это'ы стоит попробовать:
Этот взял 00:05:12.156 для запуска, который намного медленнее, чем базовый! Я'м не уверен, сможет ли он прочитать весь файл или только до линии 50 млн. до остановки, но независимо от этого не'т, кажется, как жизнеспособное решение проблемы.
Неужели
Мне показалось, что это решение с "выхода", потому что я вовсе'т собираюсь ждать полный файл для запуска:
Этот код выполнялся в 00:01:16.583, который находится всего в ~1 секунду медленнее, но все равно не лучше базового. Такими темпами если команда exit были исключены, он, вероятно, принял около ~76 минут, чтобы прочитать весь файл!
Перль
Я проверил существующие решения на Perl, а также:
Этот код выполнялся в 00:01:13.146, что в ~2 секунды быстрее, чем базовый. Если я'd и запустить его на полную 500,000,000 это, вероятно, займет ~12 минут.
ООО
Верхний ответ на доске, здесь's мой результат:
Этот код выполнялся в 00:01:12.705, что на 3 секунды быстрее, чем базовая, и ~0,4 секунды быстрее, чем Perl. Если я'd и запустить его на полную 500,000,000 строки, он, вероятно, принял ~12 минут.
карты
У меня есть bash 3.1 и поэтому не могу проверить на примере решения.
Вывод
Похоже, по большей части, это'ы трудно улучшить решение "голова ""хвост". В лучшем случае решение СЭД дает ~3% Увеличение эффективности.
(в процентах вычисляется по формуле
% = (выполнения/базовый уровень - 1) * 100
)Строки 50,000,000
ООО
на Perl
|хвост
на awk
Строки 500,000,000
ООО
на Perl
голова|хвост
на awk
Строки 3,338,559,320
ООО
на Perl
голова|хвост
на awk
С
в awk
это довольно быстро:Если это правда, то поведение значения по умолчанию
в awk
выполняется:{печати $0}
.Альтернативные версии
Если ваш файл, случается огромное, вы'выход D лучше после прочтения нужной линии. Таким образом вы экономите процессорное время.
Если вы хотите дать номер строки из Баш переменной можно использовать:
Вау, все возможности!
Попробуйте это:
или один из них в зависимости от вашей версия awk:
(Содержаться материалы, возможно, придется попробовать command_ в
nawk
илипоглазеть
).Есть ли инструмент, который не только распечатать, что конкретной линии? Не один из стандартных инструментов. Однако,
СЭД
- это, наверное, самый близкий и простой в использовании.По моим расчетам, с точки зрения производительности и читабельности моя рекомендация:
хвоста -Н+Н | глава -1`
N-это номер строки, которую вы хотите. Например, хвоста -н+7 input.txt | руководитель -1` будет печатать 7-й строке файла.
хвоста -н+н
будет печатать все, начиная от строки
П, и
Head -1` заставит его остановиться после одной линии.Руководитель -Н альтернатива
| хвост -1
, пожалуй, немного более читабельным. Например, это будет печать 7-й строке:глава -7 input.txt | хвост -1`
Когда речь заходит о производительности, нет большой разницы в меньших размерах, но он будет проигрывать в `хвосте | голове (сверху), когда файлы становятся огромными.
Топ-проголосовали-Current функциональности
sed 'NUMq;д'
интересно знать, но я утверждаю, что это будет воспринято меньше людей из коробки, чем голова/хвост решение, и это также медленнее, чем хвост/голову.В моих тестах, обе хвосты/головы превзошли версии-Current функциональности
sed 'NUMq;д'
последовательно. В соответствии с другими критериями, которые были размещены. Трудно найти случай, когда хвосты/головы было очень плохо. Это тоже не удивительно, так как эти операции, которые вы ожидаете, чтобы быть сильно оптимизирован в современной системе Unix.Чтобы получить представление о различиях в производительности, это число, которое я получаю огромный файл (9,3 г):
глава -Н | хвост -1
: 4.6 секСЭД ПД;д
: 18.8 секРезультаты могут отличаться, но голова результативность
| хвост " и " хвост | голова
, в общем-то, сопоставимы для маленьких входов, иСЭД
всегда медленнее значительным фактором (около 5X или около того).Чтобы воспроизвести мой тест, вы можете попробовать следующее, но предупредил, что это создаст файл 9.3 G в текущей рабочей директории:
Вот результат работы на моей машине (ThinkPad в Х1 карбон с SSD и 16 ГБ памяти). Я предполагаю, что в конечном итоге все выйдет из кэша, а не с диска:
Полезные однострочные скрипты для sed
Этот вопрос меткам Баш, здесь'ы Баш (≥4) способ совершения: применение
карты
с-с
(Skip) к-Н
(посчитайте) вариант.Если вам нужно получить 42-й строке файла файл``:
На данный момент, Вы'будете иметь массив
Ары
области, которая содержит строки "файл" (включая пустую строку), где мы пропустили первый 41 линии (-с 41
), и остановился после прочтения одной строки (-Н 1
). Так что's действительно 42-й строке. Чтобы распечатать его:Если вам нужен ассортимент, говорят 42-666 диапазоне (включительно), и сказать, что вы Дон'т хотите, чтобы сделать математику самостоятельно, и печатать их в stdout:
Если вам нужно обработать тоже эти строки, Это's не очень удобно хранить пустую строку. В этом случае используйте опцию
-Т
(отделка):Можно есть функция сделать это для вас:
Нет внешних команд, только Баш примитивы!
Вы также можете использовать СЭД печать и бросил:
Для этого можно также использовать Perl:
Самое быстрое решение для больших файлов всегда хвост|голову, при условии, что два расстояния:
S
е
известны. Тогда мы могли бы использовать это:
сколько всего количество необходимых линий.
Более подробно в https://unix.stackexchange.com/a/216614/79743
Все вышеперечисленные ответы прямо ответить на вопрос. Но здесь's не менее прямого решения, но потенциально более важная идея, к размышлениям.
Так как длины линий являются произвольными, все байты файла перед строкой пое нужно быть прочитанным. Если у вас есть огромный файл, или нужно повторить эту задачу много раз, и этот процесс занимает много времени, то вы должны серьезно подумать о том, следует ли вам хранить ваши данные в первую очередь.
Реальное решение-это иметь индекс, например, в начале файла, с указанием должностей, где линии начинаются. Вы могли бы использовать формат базы данных, или просто добавить таблицу в начале файла. Также можно создать отдельный индексный файл, чтобы сопровождать ваш большой текстовый файл.
например, можно создать список символьных позиций строки:
затем читать с "хвоста", который на самом деле `стремиться непосредственно к соответствующей точке в файл!
например, чтобы получить линию 1000:
Как отклик на CaffeineConnoisseur'ы очень полезно бенчмаркинг ответ... мне было интересно, как быстро 'карты' метода по сравнению с другим (как это было'т проверено), поэтому я попробовал быстрый-и-грязный скорость сравнения себя у меня есть Баш 4 удобно. Кинул в тест от "хвоста | головы" и способ (а не голова | хвост) упомянул в одном из комментариев на верхний ответ, пока я был в его, как люди поют его похвалы. Я не'т иметь ничего почти размер используемого вопросами и ответами; лучшее, что я мог найти в короткие сроки была родословная файла 14М (длинные строки, разделенных пробелами, просто под 12000 строк).
Короткая версия: Map-файла появляется быстрее, чем разрез метод, но медленнее, чем все остальное, поэтому я'д называть его пустышкой. хвост | голову, ото, похоже, это может быть самый быстрый, хотя с файлом такого размера разница не так высоки по сравнению с СЭД.
Надеюсь, что это помогает!
Используя то, что другие упомянули, я хотела, чтобы это было быстро & функция Денди в моей оболочки Bash.
Создать файл:
~/.функции
Добавить к нему содержание:
Гэтлину() { строка=$1 СЭД $линия'м;д' $2 }
Затем добавьте это в ваш~/.файл`:
источник ~/.функции`
Теперь, когда вы открываете новое окно в bash, вы можете просто вызвать функцию так:
Гэтлину myfile.txt 441
Если у вас есть несколько строк, разделенных символом \N (новая строка). Вы можете использовать 'вырезать' а также:
Вы получите 2-ю строку из файла. `
-Ф3
дает вам 3-й линии.Много уже хороших ответов. Я лично хожу с awk. Для удобства, если вы пользуетесь bash, просто добавить ниже в~/.файл`. И, при следующем входе в (Или если вы источник свой .файл после этого обновления), вы будете иметь новый отличный фильм "энное" и функцию доступной для трубы файлами через.
Выполнения той или положите его в ваш ~/.файл (если используется bash) и снова Баш (или выполнить источник ~/.bach_profile`)
# печать просто энное передается в линию ное () { на awk -vlnum=${1} 'НР==lnum {печать; выход}'; }
Затем, чтобы использовать его, просто трубу через нее. Е. Г.:
$ да линия | Кэт -Н | энный 5 Линия 5
Для печати энного через СЭД с переменной в качестве номера строки:
Здесь ' е' флаг для добавления скрипта в командной строке.
Я'ве положить некоторые из перечисленных выше ответов в короткие баш скрипт, который можно поместить в файл с именем
get.sh и ссылка на
/usr/местные/Бен/сделать` (или что другое имя вы предпочитаете).Убедитесь, что он'ы исполняемый с
Связать его, чтобы сделать его доступным на "путь" с
Ответственно понравится!
П