Como encontrar a linha mais curta em um script

1

Estou criando um script que solicita que um usuário insira um nome de arquivo e procure as linhas no arquivo, a linha mais longa e a linha mais curta. Aqui está o que eu tenho.

#!/bin/bash

echo -n "Enter a filename:"
read file
if [ -e "$file" ]
then
wc -l $file; echo "lines" && wc -L $file; echo "longest"
echo "$file exists"
else
echo "$file does not exist"
fi

Este é o conteúdo do arquivo de texto que estou usando para o teste. Espero que isso ajude.

~$ cat simple.txt
I have too many things to do today.
It's going to take to long to get everything done.
My day is very busy.
Why such a long face.

Por favor, desculpe minha formatação e / ou estrutura. Estou nos estágios iniciais de aprendizado do script de shell e aprecio qualquer ajuda.

    
por DSH72 17.11.2015 / 17:34

3 respostas

2

Se você estiver disposto a usar um pouco de Python em seu código, é fácil encontrar o tamanho da linha mais curta:

python3 -c 'import sys; print(min(map(len, sys.stdin)))' < "$file"

print e min devem ser razoavelmente óbvios. map(len, sys.stdin) aplica a função len (length) a cada entrada em sys.stdin , que é cada linha na entrada padrão. Como isso conta a nova linha no comprimento de uma linha, seu comprimento mínimo será 1 a mais do que você espera. Para corrigir isso:

python3 -c 'import sys; print(min(map(len, sys.stdin.read().splitlines())))' < "$file"

Caso contrário, uma combinação de awk , sort e head :

awk '{print length}' "$file" | sort | head -1

head -1 imprime apenas a primeira entrada, que, após a classificação, seria o comprimento de linha mais curto. Ou, inteiramente no bash:

{    
    IFS= read -r line
    min=${#line}
    while IFS= read -r line
    do
        length=${#line}
        ((min > length)) && min=$length
    done
} < "$file"

echo "shortest line's length is $min"

Aqui, usei { } para incluir a seção de código. Dessa forma, < "$file" se aplica a toda essa seção, de modo que o primeiro read e o while de leitura sejam lidos a partir dele.

    
por muru 17.11.2015 / 17:47
1

Sem usar um script, usando apenas o AWK:

awk 'NR==1{x=$0}{length($0)<length(x)&&x=$0;length($0)>length(y)&&y=$0}END{print "Shortest: "x"\nLongest: "y}' in

Se você deseja que ele solicite um nome de arquivo:

awk 'NR==1{x=$0}{length($0)<length(x)&&x=$0;length($0)>length(y)&&y=$0}END{print "Shortest: "x"\nLongest: "y}' "$(read -p "Enter a filename:" x; printf "$x\n")"

Dividindo-o em dois comandos diferentes:

awk 'NR==1{x=$0}length($0)<length(x){x=$0}END{print x}' in # shortest line
awk 'length($0)>length(x){x=$0}END{print x}' in # longest line

Se você quiser que eles solicitem um nome de arquivo:

awk 'NR==1{x=$0}length($0)<length(x){x=$0}END{print x}' "$(read -p "Enter a filename:" x; printf "$x\n")" # shortest line
awk 'length($0)>length(x){x=$0}END{print x}' "$(read -p "Enter a filename:" x; printf "$x\n")" # longest line
$ cat in
I have too many things to do today.
It's going to take to long to get everything done.
My day is very busy.
Why such a long face.
$ awk 'NR==1{x=$0}{length($0)<length(x)&&x=$0;length($0)>length(y)&&y=$0}END{print "Shortest: "x"\nLongest: "y}' in
Shortest: My day is very busy.
Longest: It's going to take to long to get everything done.
$ awk 'NR==1{x=$0}{length($0)<length(x)&&x=$0;length($0)>length(y)&&y=$0}END{print "Shortest: "x"\nLongest: "y}' "$(read -p "Enter a filename:" x; printf "$x\n")"
Enter a filename:in
Shortest: My day is very busy.
Longest: It's going to take to long to get everything done.
    
por kos 21.11.2015 / 08:27
1

No seu roteiro, há:

wc -l $file; echo "lines" && wc -L $file; echo "longest"

Você pode alterá-lo com:

LENGTH=$(<"$file" wc -l)
LONGEST=$(while read thisline; do echo "$(<<<"$thisline" wc -L) $thisline";done <"$file"|grep -v '^0 '|sort -t" "|tail -1|awk '{print $1}')
echo "$LENGTH lines, $LONGEST longest"

É isso, com alguma correção na saída do seu script.

O while cria um novo fluxo de dados, contendo o comprimento de cada linha no arquivo. O grep exclui linhas vazias (são 0 caracteres de comprimento); não há linha vazia no seu caso, mas é melhor prevenir do que remediar. Em seguida, sort coloca os comprimentos de linha em ordem crescente e tail obtém a última linha, que é o maior número (o maior comprimento de linha). awk está lá para limpar a saída (que saiu do wc , < comprimento original_line >), tendo apenas o número no início.

    
por Hydra Starmaster 19.11.2015 / 10:13