Digamos que tengo dos archivos que contienen bytes arbitrarios: ./delimiter
y ./data
.
Quiero leer desde ./data
hasta y excluyendo la primera aparición de la secuencia de bytes en ./delimiter
.
¿Cómo haría esto usando Bash?
Ejemplo:
- Contenido de
./delimiter
world
- Contenido de
./data
helloworld
- Resultado Esperado:
hello
Pregunta similar/equivalente:
Nota: read -d delim
no resuelve mi problema porque solo admite un delimitador de un solo carácter, no una cadena. Además, almacena el resultado en una variable y las variables no admiten NUL
bytes. Quiero la salida activada stdout
.
Respuesta1
Perl al rescate!
perl -e 'local $/;
open $de, "<", "delimiter" or die $!;
$/ = <$de>;
open $da, "<", "data" or die $!;
chomp( $first = <$da> );
print $first;'
La variable especial$/establece el separador de registros de entrada, mediantelocalAl leerlo leeremos el archivo completo (también llamado "slurping"). Luego usamos el operador de diamante para leer el delimiter
archivo y configuramos el separador según su contenido. Luego leemos el primer registro del data
archivo,morderseparando el registro del mismo.
Respuesta2
Con zsh
(el único shell que puede almacenar secuencias de bytes arbitrarias en sus variables), asumiendo que data
y delimiter
son archivos regulares (o al menos compatibles con mmap()), puedes hacer:
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]*}
O:
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]
(No espere que sea muy eficiente ni que se escale bien a archivos de más de unos pocos cientos de megabytes).
Para imprimir esa parte palabra por palabra, utilice:
print -rn -- $firstpart
O
printf %s $firstpart