Если Ваши сегменты не действительно огромны (как в: Вы действительно не можете сэкономить так много RAM, по-видимому, потому что это - крошечная встроенная система, управляющая большой файловой системой), единственная передача является действительно лучшим подходом. Не только, потому что это будет быстрее, но и самое главное потому что это позволяет источнику быть потоком, от которого потеряно любое чтение данных и не сохраненное. Это - действительно задание для awk, хотя sed может сделать это также.
sed -n -e 's/^---$//' -e 't a' \
-e 'H' -e '$g' -e '$s/^\n//' -e '$p' -e 'b' \
-e ':a' -e 'h' # you are not expected to understand this
awk '{if (/^---$/) {chunk=""} # separator ==> start new chunk
else {chunk=chunk $0 RS}} # append line to chunk
END {printf "%s", chunk}' # print last chunk (without adding a newline)
Если необходимо использовать подход с двумя передачами, определите смещение строки последнего разделителя и печать от этого. Или определите байтовое смещение и печать от этого.
</input/file tail -n +$((1 + $(</input/file # print the last N lines, where N=…
grep -n -e '---' | # list separator line numbers
tail -n 1 | # take the last one
cut -d ':' -f 1) )) # retain only line number
</input/file tail -n +$(</input/file awk '/^---$/ {n=NR+1} END {print n}')
</input/file tail -c +$(</input/file LC_CTYPE=C awk '
{pos+=length($0 RS)} # pos contains the current byte offset in the file
/^---$/ {last=pos} # last contains the byte offset after the last separator
END {print last+1} # print characters from last (+1 because tail counts from 1)
')
Приложение: Если у Вас есть больше, чем POSIX, вот простая версия с одной передачей, которая полагается на общее расширение awk, который позволяет разделитель записей RS
быть регулярным выражением (POSIX только позволяет отдельный символ). Это не абсолютно корректно: если файл заканчивается разделителем записей, он печатает блок перед последним разделителем записей вместо пустой записи. Второе использование версии RT
избегает того дефекта, но RT
характерно для GNU awk.
awk -vRS='(^|\n)---+($|\n)' 'END{printf $0}'
gawk -vRS='(^|\n)---+($|\n)' 'END{if (RT == "") printf $0}'
То, о чем Вы говорите, называют кластером Изображения Единой системы или иногда распределенной системой с разделяемой памятью (в большем количестве ограничивающего контекста). Существуют некоторые проекты, перечисленные на связанных страницах Wikipedia, которые необходимо изучить. Я использовал SGI Altix кластер (NUMAlink), и может быть довольно мощно, если у Вас есть процесс, который требует огромного объема потребляемой памяти.
С увеличением скорости ЦП и емкости памяти отдельных узлов, это, кажется, больше меньше популярного вычислительного метода кластеризации. Большинство людей использует API передачи сообщений, чтобы позволить параллельному вычислению связываться по быстрому взаимосвязанному или простому Ethernet.
Нет никакого способа "просто" объединить ресурсы отдельных машин. Программное обеспечение, которое Вы запускаете сверх своего кластера, должно быть записано с параллелью в памяти. Вы не можете ожидать, что единственное вычисление интенсивный процесс волшебно распадется между несколькими ядрами или даже машинами. И даже если программное обеспечение записано для параллельного выполнения, после того как Вы идете с нескольких ядер на несколько машин, можно легко столкнуться с узким местом передачи сообщений по медленному сетевому каналу промежуточные машины.
Мне любопытно, каковы были "решения устаревшие", которые Вы нашли до сих пор? Кто-либо из тех делает то, что Вы ищете?