Я пытаюсь использовать каждую первую букву первого слова в каждом предложении из txt-файла с именем input.txt и хочу, чтобы этот входной файл был аргументом сценария оболочки
./script.sh input.txt
sample входной файл:
i am Andrew. you are Jhon. here we are, forever.
файл результата:
I am Andrew. You are Jhon. Here we are, forever.
Особый случай. Что если наш текст (связанный с ответом @RaduRadeanu)
i am andrew. you
are jhon. here we are
forever
будет иметь следующий результат:
I am andrew. You
Are jhon. Here we are
Forever.
Таким образом, он преобразует в верхний регистр каждое первое слово каждого предложения, а также каждое первое слово новой строки. Как нам пропустить первое слово новой строки в верхнем регистре?
Таким образом, правильный результат должен быть:
I am andrew. You
are jhon. Here we are
forever.
Что, если предложение закрывается в «?» или же "!" ???
sed
команда очень мощна для редактирования файлов из сценариев оболочки. С его справкой можно отредактировать однако, Вы хотите текстовый файл. Они сказанные, следующий сценарий могут сделать то, чего Вы желаете:
#!/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 !
Для Вашего особого случая вещи стали немного:
#!/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
Кроме того, можно консультироваться с этим учебным руководством: Unix - Регулярные выражения с SED, чтобы видеть, как работать в этих ситуациях.
Как насчет того, чтобы использовать встроенное 'чтение' удара функционируют с символом точки как разделитель, чтобы считать каждое целое предложение в переменную и затем использовать для своей выгоды начальный символ переменной? Что-то как
$ 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.
Обработать несколько разделителей предложения, например? и! а также регулярный период, вот другой подход с помощью 'awk' - отмечают, что переменная RT, которая позволяет нам восстанавливать конкретный рекордный разделитель, который соответствовал конкретному предложению, является расширением, которое не может быть доступно во всех вариантах '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!
Обратите внимание, что разделитель записей regex выше обработает несколько последовательных разделителей ('!?!!!') и дополнительные конечные пробелы - который не делает основанная на чтении версия.
Как дальнейшее улучшение, давайте попытаемся добавить элементарную обработку заключенных в кавычки предложений путем изменения RS regex еще раз и изменения sub так, чтобы это верхние регистры первый несимвол кавычки:
awk 'BEGIN{RS="[.!?]+[\"'\'']?[ \t\n]*"}; {match($0, "[^\"'\'']"); sub("[^\"'\'']", substr(toupper($0),RSTART,1), $0); printf ("%s%s", $0, RT)}'
например.
$ 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!?'