bash: lee desde la entrada estándar hasta un delimitador de cadena

bash: lee desde la entrada estándar hasta un delimitador de cadena

Digamos que tengo dos archivos que contienen bytes arbitrarios: ./delimitery ./data.

Quiero leer desde ./datahasta 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 delimno 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 NULbytes. 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 delimiterarchivo y configuramos el separador según su contenido. Luego leemos el primer registro del dataarchivo,morderseparando el registro del mismo.

Respuesta2

Con zsh(el único shell que puede almacenar secuencias de bytes arbitrarias en sus variables), asumiendo que datay delimiterson 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

información relacionada