Команда Sed для удаления строк - переменная

Слишком медленно? Что вы ожидаете? У вас около миллиона строк в этом файле, скажем, 12 МБ. Теперь для каждой строки другого файла вы должны просмотреть весь этот файл. Вы можете сказать, что сравнение останавливается после первого байта в девяти из десяти случаев, но даже в этом случае вам придется продолжать поиск следующей новой строки, так что на самом деле для каждой строки второго файла каждый байт первого файла имеет пройти через ЦП.

Теперь этот второй файл может содержать один миллиард строк. Итак, вам нужно отсканировать один миллиард раз по 12 МБ, это 12 эксабайт! Теперь, если ваш настольный компьютер имеет 8 МБ кэш-памяти L3, эти 12 МБ не подходят и должны быть извлечены из вашей оперативной памяти. К счастью, оперативная память в наши дни работает быстро, возможно, ваша машина имеет эффективную пропускную способность 20 ГБ/с. Если я правильно рассчитал, для доступа к 12 Exebyte со скоростью 20 ГБ/с требуется 600 000 секунд. 10.000 минут. 167 часов. 7 дней. Неделя.

Но это не медленно, это очень быстро! Это займет очень много времени, так как это огромная задача.

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

Как? Используйте быстрый язык, такой как C, и сначала организуйте данные вашего файла1, чтобы вам не приходилось просматривать их все. Поместите каждую запись в дерево. Корень имеет десять указателей на поддеревья, в зависимости от первой цифры. Каждое поддерево имеет еще десять указателей на поддеревья, если только нулевой указатель не указывает на то, что здесь нет листьев.

Теперь при сканировании через файл2 вы берете первый байт и получаете указатель в соответствии с этой цифрой, в этом поддереве выбираете указатель для второй цифры и так далее. Для восьмизначных и 64-битных указателей в худшем случае (найдено совпадение )только 64 байта, которые вы должны загрузить, плюс байты, хранящиеся в этом, остаются с именем. Может быть, 80 байт на строку, миллиард раз умножается на 80 ГБ, извлекается из памяти за 4 секунды. Звучит лучше, не так ли?

Это более быстрый способ сделать это, но он не связан с Unix. Если вы не знаете, как написать подобную программу, вам следует задать вопрос на StackOverflow. Вы можете обратиться сюда.

1
22.09.2019, 00:13
1 ответ

Как указано в комментарии , вам необходимо правильно заключать переменные в кавычки при вызове sed:

for i in $(seq 1 6 99); do
    sed "$i"','"$((i+2))"'!d' test.txt > "o$i.txt"
done

Ваши переменные не раскрываются в одинарных кавычках и воспринимаются буквально($i= вставить перед последней строкой ). Расширение работает с двойными кавычками (в этом примере также не работают кавычки )и вам нужно $((…))для арифметического вычисления и вывода его результата. Остальные части скрипта остаются в одинарных кавычках.

Вы также должны использовать более новый синтаксис $(…)для подстановки команд вместо устаревших обратных кавычек `…`, что упрощает цитирование. Вот хороший пример .


Но вы можете использовать оператор GNU sedпервого ~шага вместо цикла:

sed '4~6{N;N;d}' file

Пример:

$ seq 20 | sed '4~6{N;N;d}'
1
2
3
7
8
9
13
14
15
19
20

Пояснение:

sed '4~6d'удалит строку 4, а затем каждую 6-ю строку 10, 16, 22...

С помощью {N;N;d}удаляются две дополнительные строки: 4,5,6, затем 10,11,12...

4
27.01.2020, 23:22

Теги

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