Eu tenho um arquivo de texto que estou produzindo para uma variável no meu script de shell. Só preciso dos 50 primeiros caracteres.
Eu tentei usar, cat ${filename} cut -c1-50
mas estou ficando muito mais do que os 50 primeiros caracteres? Isso pode dever-se à cut
procura de linhas (sem 100% de certeza), enquanto esse arquivo de texto pode ser uma cadeia longa - realmente depende.
Existe um utilitário por aí que eu possa usar para obter os primeiros caracteres X de um cat
comando?
|
?cat ${filename} | cut -c1-50
Respostas:
Isso retorna os primeiros 50 bytes.
Lembre-se de que o comando nem sempre é implementado da mesma forma em todos os sistemas operacionais. No Linux e macOS, ele se comporta dessa maneira. No Solaris (11), você precisa usar a versão gnu em / usr / gnu / bin /
fonte
-c
opção. Eu iria para dd (1) em vez disso.GNU coreutils 5.97
) sim.-c
como uma opção válida, no entanto, portanto, é definitivamente dependente do seu ambiente local. unix.com/man-page/posix/1/headSeu
cut
comando funcionará se você usar um canal para passar dados para ele:Ou, evitando um uso inútil do gato e tornando-o um pouco mais seguro:
Observe que os comandos acima imprimirão os primeiros 50 caracteres (ou bytes, dependendo da sua
cut
implementação) de cada linha de entrada . Ele deve fazer o que você espera se, como você diz, seu arquivo for uma linha enorme.fonte
Isso retorna os primeiros 50 bytes.
fonte
status=none
bandeira. Use em2>/dev/null
vez disso (e cite corretamente):dd if="$filename" bs=1 count=50 2>/dev/null
(mesmo assim, considere usarbs=50 count=1
para reduzir o número de syscalls envolvidos).status=none
ao usar o Ubuntu 14.04, coreutils 8.21, mas você está certo em usar2>/dev/null
uma versão anterior.read()
dos 50 bytes. Sefile
for um canal, por exemplo, e menos caracteres estiverem disponíveis no momento, menos bytes serão retornados. Para ter o equivalente ahead -c50
, você precisaria usar o específico do GNUiflag=fullblock
.Até agora, a maioria das respostas assume que 1 byte = 1 caractere, o que pode não ser o caso se você estiver usando um código de idioma não ASCII.
Uma maneira um pouco mais robusta de fazer isso:
Observe que isso pressupõe:
ksh93
,bash
(ou uma recentezsh
oumksh
(embora o único charset multi-byte apoiado pormksh
é UTF-8 e só depoisset -o utf8-mode
)) e uma versão dehead
que os suportes-c
(a maioria faz hoje em dia, mas não estritamente standard).locale charmap
efile -- "$filename"
verifique isso); caso contrário, defina-o com ie.LC_ALL=en_US.UTF-8
)head
, assumindo o pior caso UTF-8, em que todos os caracteres são codificados com no máximo 4 bytes. Isso deve cobrir a maioria dos casos em que consigo pensar.fonte
head
, ou outra implementação do mesmo que adiciona a-c
opção não padrão . Mas você já está exigindo o GNU bash. (Nota:mksh
o modo UTF-8 do pode fazer isso para arquivos codificados em UTF-8.) Gostaria de perguntar ao OP se eles exigem caracteres octetos ou multibyte, apenas "caracteres" é um termo vago / genérico.$filename
ou$testString
não contém nova linha ou curingas em branco ou para começar-
.${var:offset:length}
construção que você está usando aqui é realmente origináriaksh93
e também é suportada por versões recentes dezsh
(zsh
possui sua própria$testString[1,50]
). Você precisa${testString:0:50}
noksh93
ezsh
no entanto.Outra variante (para a primeira linha do arquivo)
fonte
read
eecho
? Oubash expansion
?grep
(regexp) e sim, o uso de shell aqui (dica: a primeira linha pode ser grande). (Dito isto, o Bashismo também não está na POSIX, mas a maioria das conchas implementar isso.)1. Para arquivos ASCII, faça como @DisplayName diz:
imprimirá os primeiros 50 caracteres do arquivo.txt, por exemplo.
2. Para dados binários, use-os
hexdump
para imprimi-los como caracteres hexadecimais:imprimirá os primeiros 50 bytes de file.bin, por exemplo.
Observe que, sem a
-v
opção detalhada,hexdump
substituiria linhas repetidas por um asterisco (*
). Consulte aqui: https://superuser.com/questions/494245/what-does-an-asterisk-mean-in-hexdump-output/494613#494613 .fonte
Você pode usar o sed para isso, que resolverá o problema com bastante facilidade
fonte
sed -n -e '1s/^\(.\{50\}\).*/\1/p' ${filename}