Как изменить любой текст на правильный регистр и регистр предложения с помощью tr?

На данный момент эта функция не поддерживается в NordVPN для Linux. Я надеюсь, что этот ответ скоро станет устаревшим.

1
30.11.2019, 10:11
3 ответа

trтолько изменяет одиночные символы на другие одиночные символы (или удаляет их ), и имеет смысл контекста любого символа. Поэтому он не может различить символ в начале, середине или конце слова. Оно даже не знает, что такое «слово».

Изменение текста на заглавный регистр(то, что вы называете "правильным регистром" )или на регистр предложения невозможно с помощью tr.

Вам нужен инструмент, который можно использовать для придания контекста отдельному персонажу.

Это наивная программа GNU sed, которая преобразует текст в регистр заглавий, сопоставляя отдельные слова и изменяя их первый символ:

$ sed 's/\<\([[:lower:]]\)\([[:alnum:]]*\)/\u\1\2/g' file
There Is No Danger On The Roof. There Is No Cow On The Ice.

\<совпадает в точке перехода между символом слова, отличным от -, и символом слова (, т. е. в начале слова ). Остальная часть регулярного выражения соответствует строчной букве, за которой следует любое количество буквенно-цифровых символов. Если он совпадает, он меняет строчную букву на прописную и добавляет остальную часть слова. Верхний -регистр первой буквы использует расширение GNU sed(, это не будет работать в большинстве других sedреализаций ).

Для обрамления текста предложения, еще одна наивная вариация GNU sed:

$ sed 's/\<\([[:lower:]]\)\([^[:punct:]]*\)/\u\1\2/g' file
There is no danger on the roof. There is no cow on the ice.

Это снова более или менее то же самое, но вместо того, чтобы сопоставлять слово из буквенно-цифровых символов, мы сопоставляем строку символов, которые не являются знаками препинания.

Обратите внимание, что это работает только с очень простыми текстами того типа, который вы указали в вопросе. Второй sed, например, не справился бы должным образом с вопросом what's that?из-за того, что 'является знаком пунктуации, соответствующим [[:punct:]].

1
27.01.2020, 23:17

Нет, одним trне обойтись. trне понимает слов или предложений, необходимых для выполнения этой работы.

В качестве альтернативы вы можете попробовать Perl с его мощным механизмом шаблонов:

$ perl -pe 's/\b[\p{L}\p{Pd}]+/ucfirst lc $&/ge' <<< 'A HEART-SHAPED BOX'
A Heart-shaped Box
$ perl -pe 's/\p{L}.*?[.?!]/ucfirst lc $&/ge' <<< 'for sale. baby shoes. never worn.'
For sale. Baby shoes. Never worn.

Вышеприведенное, однако, является быстрым -и -грязным решением и не охватывает все возможные случаи и настройки, которые можно было бы применить здесь (не -латинский алфавит и не -Латинские буквы ASCII, локаль -зависимый падеж, артикли не пишутся с заглавной буквы, имена собственные в предложениях пишутся с большой буквы и т. д. ).С другой стороны, никто trне может этого сделать.

1
27.01.2020, 23:17

Обратите внимание: если ваша оболочка не fish, которая не поддерживает оператор подстановки [...], вы должны заключать эти [:lower:], [A-Z]в кавычки, иначе они могут быть расширены оболочкой до списка соответствующих файлов. в текущем каталоге (или сообщить об ошибке, если совпадений нет):

tr '[:lower:]' '[:upper:]'

Другие примечания:

  • реализация GNU trподдерживает только однобайтовые символы, поэтому в локали UTF -8 она будет использовать только заглавные английские буквы без диакритических знаков.
  • tr '[A-Z]' '[a-z]'подходит, но вы также можете просто выполнитьtr A-Z a-z(в POSIX-совместимых реализациях ). Однако гарантируется совпадение только с ABCDEFGHIJKLMNOPQRSTUVWXYZв локали C/POSIX.

Чтобы сделать первую букву каждого слова заглавной, с реализацией GNU sed, вы можете сделать:

sed -E "s/[[:alnum:]_'-]+/\u&/g"

Мы включаем ', -и _, но никакие другие знаки препинания, чтобы превратить foo-bar2baz,fooв Foo-bar2baz,Foo.

Это работает с многобайтовыми -символами, но, как правило, не с комбинированными символами, так как большинство локалей не будут рассматривать их какalnum:

$ echo $'ste\u0301phane' | sed -E "s/[[:alnum:]_']+/\u&/g"
StéPhane

Чтобы рассмотреть их, вы можете переключиться на perl, где их можно сопоставить с\pM:

$ echo $'ste\u0301phane chazelas' | perl -Mopen=locale -pe 's/[\w\pM'\''-]+/\u$&/g'
Stéphane Chazelas

Для написания предложения с заглавной буквы это довольно сложно, вы должны сделать заглавной первую букву, найденную в начале текста или после разделителя предложения (, например ., ?, … )или введение предложения (¿, ¡), допускающее любое количество пробелов между ними, а также такие вещи, как (, [, ", , , «… ). В зависимости от того, какой язык (и )вы хотите поддерживать, вы можете рассмотреть дополнительные возможности.

Вы можете сделать это с помощью perlс чем-то вроде:

perl -0777 -C -pe 's/(^|[.!?…⁇⁈⁉¿¡])[\s([{"`‶‷«]*\K\p{lL}/\u$&/g'

Здесь предполагается локаль UTF -8 и входные данные, и охватываются лишь некоторые из этих случаев.

В любом случае, это не то, что можно сделать с trв одиночку, так как trтранслитерировать каждый символ,нельзя сказать транслитерировать только некоторые.

2
27.01.2020, 23:17

Теги

Похожие вопросы