Допустим, у меня есть два файла, содержащих произвольные байты: ./delimiter
и ./data
.
Я хочу прочитать данные ./data
до первого вхождения последовательности байтов в файле ./delimiter
.
Как это сделать с помощью Bash?
Пример:
- Содержание
./delimiter
world
- Содержание
./data
helloworld
- Ожидаемый результат:
hello
Похожий/эквивалентный вопрос:
Примечание: read -d delim
не решает мою проблему, поскольку поддерживает только односимвольный разделитель, а не строку. Кроме того, он сохраняет результат в переменной, а переменные не поддерживают NUL
байты. Я хочу вывод в stdout
.
решение1
Perl спешит на помощь!
perl -e 'local $/;
open $de, "<", "delimiter" or die $!;
$/ = <$de>;
open $da, "<", "data" or die $!;
chomp( $first = <$da> );
print $first;'
Специальная переменная$/устанавливает разделитель входных записей,местныйЕсли мы его используем, мы прочитаем весь файл (также называется "прихлебывание"). Затем мы используем оператор ромба для чтения из файла delimiter
и устанавливаем разделитель на его содержимое. Затем мы считываем первую запись из data
файла,чавкатьизвлекая из него разделитель записей.
решение2
С помощью zsh
(единственной оболочки, которая может хранить произвольные последовательности байтов в своих переменных), предполагая, что data
и delimiter
являются обычными (или, по крайней мере, поддерживающими mmap()) файлами, вы можете сделать следующее:
zmodload zsh/mapfile
set +o multibyte # necessary so sequences of bytes that
# happen to form valid characters may be
# broken in the middle if necessary.
firstpart=${mapfile[data]%%$mapfile[delimiter]*}
Или:
zmodload zsh/mapfile
set +o multibyte # necessary so sequences of bytes that
# happen to form valid characters may be
# broken in the middle if necessary.
delimiter=$mapfile[delimiter]
parts=( ${(ps[$delimiter])mapfile[data]} )
firstpart=$parts[1]
(не ожидайте, что он будет очень эффективным или хорошо масштабируется для файлов размером более нескольких сотен мегабайт).
Чтобы распечатать эту часть дословно, используйте:
print -rn -- $firstpart
Или
printf %s $firstpart