Como a primeira letra maiúscula da primeira palavra em cada frase usando o shell script?

5

Eu estou tentando capitalizar cada primeira letra da primeira palavra em cada sentença de um arquivo txt chamado input.txt e quero que esse arquivo de entrada seja um argumento do shell script

 ./script.sh input.txt

arquivo de entrada de amostra:

i am Andrew. you are Jhon. here we are, forever.

arquivo de resultado:

I am Andrew. You are Jhon. Here we are, forever.

Um caso especial. E se o nosso texto for (relacionado à resposta @RaduRadeanu)

i am andrew. you
are jhon. here we are
forever

o resultado seria:

I am andrew. You
Are jhon. Here we are
Forever.

Por isso, converte em maiúsculas cada primeira palavra de cada frase e também cada primeira palavra da nova linha. Como podemos pular a primeira palavra em maiúsculas da nova linha?

Portanto, o resultado correto deve ser:

I am andrew. You
are jhon. Here we are
forever.

E se a frase for fechada em "?" ou "!" ???

    
por Adrian George 19.08.2013 / 16:30

2 respostas

4
O comando

sed é muito poderoso para editar arquivos a partir de scripts de shell. Com sua ajuda, você pode editar como quiser um arquivo de texto. Dito isso, o script a seguir pode fazer o que você deseja:

#!/bin/bash

#check if a file is given as argument
if [ $# -ne 1 ];then
  echo "Usage: 'basename $0' FILE NAME"
  exit 1
fi

sed -i 's/^\s*./\U&\E/g' $@         #capitalize first letter from a paragraf/new line
sed -i 's/[\.!?]\s*./\U&\E/g' $@    #capitalize all letters that follow a dot, ? or !

Para o seu caso especial, as coisas ficaram um pouco:

#!/bin/bash

#check if a file is given as argument
if [ $# -ne 1 ];then
  echo "Usage: 'basename $0' FILE NAME"
  exit 1
fi

sed -i '1s/^\s*./\U&\E/g' $@  #capitalize first letter from the file
sed -i 's/\.\s*./\U&\E/g' $@  #capitalize all letters that follow a dot

#check if the a line ends in dot, ? or ! character and 
#if yes capitalize first letter from the next line
next_line=0
cat $@ | while read line ;do
  next_line=$[$next_line+1]
  lastchr=${line#${line%?}}
  if [ "$lastchr" = "." ] || [ "$lastchr" = "!" ] || [ "$lastchr" = "?" ]; then
    sed -i "$[$next_line+1]s/^\s*./\U&\E/g" $@
  fi
done

Além disso, você pode consultar este tutorial: Unix - Expressões regulares com o SED para ver como para trabalhar nessas situações.

    
por Radu Rădeanu 19.08.2013 / 17:04
4

Que tal usar a função de 'leitura' de bash com o caractere de período como delimitador para ler cada sentença inteira em uma variável e, em seguida, capitalizar o caractere inicial da variável? Algo como

$ cat myfile
i am andrew. you
are jhon. here we are
forever.

$ while read -rd\. sntc; do printf "%s. " "${sntc^}"; done < myfile; printf "\n"
I am andrew. You
are jhon. Here we are
forever.

Para lidar com vários terminadores de frase, por ex. ? e! bem como o período regular, aqui está uma abordagem diferente usando 'awk' - note que a variável RT que nos permite recuperar o terminador de registro particular que corresponde a uma sentença específica é uma extensão que pode não estar disponível em todas as variedades de 'awk '

$ cat myfile
i am andrew? you
are jhon. here we are
forever!

$ awk 'BEGIN{RS="[.!?]+[ \t\n]*"}; {sub(".", substr(toupper($0), 1,1), $0); printf ("%s%s", $0, RT)}' myfile
I am andrew? You
are jhon. Here we are
forever!

Observe que a regex do separador de registros acima tratará de vários delimitadores consecutivos ('!? !!!') e espaços finais opcionais - o que a versão baseada em leitura não faz.

Como um aprimoramento adicional, vamos tentar adicionar um tratamento rudimentar de sentenças citadas modificando o regex RS mais uma vez e alterando o sub para que maiúsculas o primeiro caractere não-aspas :

awk 'BEGIN{RS="[.!?]+[\"'\'']?[ \t\n]*"}; {match($0, "[^\"'\'']"); sub("[^\"'\'']", substr(toupper($0),RSTART,1), $0); printf ("%s%s", $0, RT)}'

por exemplo,

$ cat myfile
i am andrew.    "are
you jhon?"  'here we are
forever!?'

$ awk 'BEGIN{RS="[.!?]+[\"'\'']?[ \t\n]*"}; {match($0, "[^\"'\'']"); sub("[^\"'\'']", substr(toupper($0),RSTART,1), $0); printf ("%s%s", $0, RT)}' myfile
I am andrew.    "Are
you jhon?"  'Here we are
forever!?'
    
por steeldriver 19.08.2013 / 19:36

Tags