Como obter a string mais curta em um arquivo de texto com shell

3

Suponha que eu tenha um arquivo de texto como abaixo

abcd
aaaaaaa
gfgk
hahahahahahhahh
gf

Em seguida, gf seria devolvido.Quaisquer boas ideias?

    
por SpawnST 29.04.2010 / 03:02

5 respostas

7

Supondo que suas linhas contenham uma "palavra" de caracteres,
e, não nos importamos em deixar a casca fazer um pouco mais de trabalho,
Aqui está uma solução AWK.

# Let your text be in 'str.txt'

awk '{print length($1), $1}' str.txt | sort -nk 1 | head -1

# Output: 2 gf ## Which is the shortest string

Você pode otimizar isso para evitar uma classificação com mais alguns AWK.
Você pode ajustar isso ainda mais se tiver mais de uma palavra por linha.

Observe também que, se você tiver várias strings mais curtas, isso dará a você uma delas.
Você pode fazer mais alguns truques para obtê-los também.

    
por 29.04.2010 / 04:40
10

Awk é ótimo para isso:

awk '(NR == 1 || length < length(shortest)) { shortest = $0 } END { print shortest }'

A primeira parte define a variável "mais curta" para a linha atual se for a primeira linha ou se o comprimento for menor que a linha mais curta vista anteriormente. Finalmente, a última parte mostra o valor do menor.

    
por 29.04.2010 / 05:21
3

FAQ BASH entrada # 1 diz como ler um arquivo linha por linha. ${#foo} fornecerá o comprimento de $foo . Apenas loop, testando cada linha por vez.

    
por 29.04.2010 / 03:27
2

Uma solução usando sed e mantendo a primeira linha mais curta do arquivo:

sed -e '1h;H;g;s/[^\n]/#/g;s/\(#*\)\n/\n/;G;/^\n/s/\n.*\n\(.*\)\n.*//;s/.*\n//;h;$!d' your_file

Para manter a última linha mais curta do arquivo:

sed -e '1h;G;h;s/[^\n]/#/g;s/\(#*\)\n/\n/;G;/^\n/s/\n.*\n\(.*\)\n.*//;s/.*\n//;h;$!d' your_file

Abaixo está uma versão explicada da primeira linha mais curta na forma de um arquivo de script sed que pode ser executado usando sed -f script your_file :

# The hold space will contain the shortest line at the beginning and the ending of each cycle.
# The 1st line is the shortest, so put it in the hold space so an empty line will not be returned.
1h
# Append the current line to the shortest so far, remember these 2 lines in the hold space, and take a copy in the pattern space to work on them.
H;g
# Replace all chars by #.
s/[^\n]/#/g
# Delete the same number of # before and after the line delimiter.
s/\(#*\)\n/\n/
# Append the 2 lines remembered in the hold space to the pattern space.
G
# If the hold space begin by a '\n', the current line was shorter, so keep it.
/^\n/s/\n.*\n\(.*\)\n.*//
# Else, the previous line was shorter, so keep it.
s/.*\n//
# Remember shortest in hold space.
h
# If last line, print it (delete everything else).
$!d
    
por 21.08.2011 / 18:29
0

Aqui está minha oferta bastante desajeitada usando o Perl:

grep . file | perl -E '@a=<>; @s = sort {length $a <=> length $b}@a; say $s[0] . "Line $."; '
    
por 09.11.2018 / 16:11