Pegar os primeiros [x] caracteres de uma string em um pipe


Respostas:


82

Uma maneira é usar cut:

 command | cut -c1-8

Isso fornecerá os 8 primeiros caracteres de cada linha de saída. Como cutfaz parte do POSIX, é provável que esteja na maioria dos Unices.


3
Observe que cut -cseleciona caracteres; cut -bou head -cseleciona bytes. Isso faz a diferença em alguns locais (na prática, ao usar UTF-8).
Gilles 'SO- stop be evil'

Você também não precisa especificar o índice inicial neste caso. Dizendo cut -c-8vai selecionar a partir de caráter 1 a 8.
Sparhawk

@Steven, cuté equivalente no Windows é?
Pacerier

Também command | dd bs=8 count=1 2>/dev/null. Não estou dizendo que é mais curto ou superior. Apenas outra alternativa.
dubiousjim

@Gilles, mas observe que nas versões atuais do GNU cut, cut -cfunciona assim cut -b(ou seja, não funciona corretamente para caracteres de vários bytes).
Stéphane Chazelas

24

Existem outras maneiras de obter apenas os 8 primeiros caracteres.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

E se você tiver festança

var=$(command)
echo ${var:0:8}

2
Eu acho que a seguinte formulação sed é um pouco mais fácil de ler: command | sed 's/\(.\{8\}\).*/\1/'ou se seus suportes sed-lo: command | sed -r 's/(.{8}).*/\1/'; Caso contrário, +1
Steven D

Coisas boas, mas observe que head -cconta bytes , não caracteres. Da mesma forma, entre as principais implementações do Awk, apenas o GNU awk lida com caracteres de vários bytes corretamente - o FreeBSD Awk e o Mawk não.
mklement0

2

Se você tiver um shell suficientemente avançado (por exemplo, o seguinte funcionará no Bash, não tenho certeza sobre o traço), você pode:

read -n8 -d$'\0' -r <(command)

Após a execução read ... <(command), seus caracteres estarão na variável shell REPLY. Digite help readpara aprender sobre outras opções.

Explicação: o -n8argumento para readdiz que queremos até 8 caracteres. O -d$'\0'diz lê até um nulo, em vez de uma nova linha. Dessa forma, a leitura continuará com 8 caracteres, mesmo que um dos caracteres anteriores seja uma nova linha (mas não se for nulo). Uma alternativa -n8 -d$'\0'é usar -N8, que lê exatamente 8 caracteres ou até que o stdin atinja o EOF. Nenhum delimitador é respeitado. Provavelmente isso atende melhor às suas necessidades, mas não sei de antemão quantas conchas têm uma leitura que seja honrada, -Nem vez de honrar -ne -d. Continuando com a explicação: -rdiz ignore \-escapes, de modo que, por exemplo, tratamos \\como dois caracteres, e não como um único \.

Finalmente, fazemos read ... <(command)mais do que command | read ...porque, na segunda forma, a leitura é executada em um subshell que é encerrado imediatamente, perdendo as informações que você acabou de ler.

Outra opção é fazer todo o processamento dentro do subshell. Por exemplo:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>

11
Se você deseja apenas produzir os 8 caracteres e não precisar processá-los no shell, basta usar cut.
dubiousjim

É bom saber sobre read -n <num>; pequena ressalva: o Bash 3.x (ainda atual no SO) interpreta erroneamente <num>como uma contagem de bytes e, portanto, falha com caracteres de vários bytes; isso foi corrigido no Bash 4.x.
mklement0

Esta é uma resposta ótima e útil. Muito mais geral que os outros.
not2qubit 25/10

2

Outra solução de um liner usando expansão de parâmetro

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell

Você também pode usar uma variável com o comprimento, por exemplo: em x=8; echo ${word:0:$x}vez de codificar o número inteiro.
Cometsong 25/04

1

Isso é portátil:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Para criar uma sequência de caracteres de tamanho variável, você tem sua própria pergunta aqui .


0

Eu tive esse problema ao gerar manualmente arquivos de soma de verificação no repositório maven. Infelizmente, cut -csempre imprime uma nova linha no final da saída. Para suprimir que eu uso xxd:

command | xxd -l$BYTES | xxd -r

Ele gera exatamente $BYTESbytes, a menos que a commandsaída seja mais curta, exatamente essa saída.


outro método para decolar cuta nova linha de fuga é | tr -d '\n'
inseri-
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.