bash: Lê de stdin até um delimitador de string

bash: Lê de stdin até um delimitador de string

Digamos que eu tenha dois arquivos contendo bytes arbitrários: ./delimitere ./data.

Quero ler ./dataaté e excluindo a primeira ocorrência da sequência de bytes em ./delimiter.

Como eu faria isso usando o Bash?

Exemplo:

  • Conteúdo de./delimiter
    world
    
  • Conteúdo de./data
    helloworld
    
  • Resultado esperado:
    hello
    

Pergunta semelhante/equivalente:

Nota: read -d delimnão resolve meu problema, pois suporta apenas um delimitador de caractere único, não uma string. Além disso, armazena o resultado em uma variável e as variáveis ​​não suportam NULbytes. Eu quero a saída em stdout.

Responder1

Perl para o resgate!

perl -e 'local $/;
         open $de, "<", "delimiter" or die $!;
         $/ = <$de>;
         open $da, "<", "data" or die $!;
         chomp( $first = <$da> );
         print $first;'

A variável especial$/define o separador de registro de entrada, porlocalAo fazer isso, leremos o arquivo inteiro (também chamado de "slurping"). Em seguida, usamos o operador diamante para ler o delimiterarquivo e definir o separador para seu conteúdo. Em seguida, lemos o primeiro registro do dataarquivo,mastigarseparando o separador de registros dele.

Responder2

Com zsh(o único shell que pode armazenar sequências de bytes arbitrárias em suas variáveis), assumindo datae delimitersão arquivos regulares (ou pelo menos mmap() capazes), você pode fazer:

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]*}

Ou:

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]

(não espere que seja muito eficiente nem que seja bem dimensionado para arquivos maiores que algumas centenas de megabytes).

Para imprimir essa parte literalmente, use:

print -rn -- $firstpart

Ou

printf %s $firstpart

informação relacionada