POSIXly:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
Это не будет работать, если строка начинается или заканчивается недействительным байтовым символом, если вы хотите охватить этот случай, вы можете добавить LC_ALL=C
, хотя LC_ALL=C
работает только с однобайтовыми символьными данными.
perl6
кажется лучшим инструментом, если он у вас в коробке:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Хотя это все еще задыхается от недопустимых символов.
Обратите внимание, что perl6
изменит ваш текст, превратив его в NFC
форму:
$ printf '\u0044\u0323\u0307\n' |
perl6 -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a
$ printf '\u0044\u0323\u0307\n' |
perl -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a
Внутри perl6
хранится строка в NFG
форме (обозначать Normalization Form Grapheme
), которая perl6
придумана для правильной работы с предварительно не скомпонованными графемами:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6
изменит текст, хотя (превратить его в NFC (нормализованная форма "составлено")).perl6
- это store inNFG
form (G
forGrapheme
), что позволяетperl6
правильно обрабатывать нескомпонованные графемы.Не grep, а awk:
Эти особые случаи обрабатываются:
Пустой FS разделяет запись на один символ на поле в
gawk
,mawk
иbusybox
awk
(байты, а не символы для последних двух), но не является стандартным и не работает в реализациях,awk
производных от исходного A, W и K, как на BSDs и коммерческих единицах. Более портативный, но больше для ввода:источник
FS
пустая строка не является стандартной и не будет работать в некоторыхawk
реализациях.awk 'length&&substr($0,1,1)==substr($0,length)'
(обратите внимание, что по умолчанию используется аргументlength
is$0
, а действие по умолчанию is{print $0}
)nawk
почти так же плохо :-)Пример:
-x
для точного соответствия (совпадение по всей строке).\1
являясь обратной ссылкой на персонажа, захваченного в\(.\)
. Мы добавляем a,-e .
чтобы позаботиться о специальном случае строки, содержащей один единственный символ.Предполагается, что ввод содержит действительный текст в текущей локали.
Соответствие идет по символу , а не по байту (например, é в UTF-8 - это два байта 0xc3 0xa9), или кластер graphem (он не будет работать, если эти é были записаны в разложенном виде с
e
последующим U + 0301 например, сочетая острый акцент).Для работы на кластерах графема с
grep
поддержкой-P
PCRE:При этом предполагается, что разложение является одинаковым для двух кластеров, например,
ḉ
выражение,c
U+0301
U+0327
которое не соответствует, выражается какc
U+0327
U+0301
илиć
(U+0107
)U+0327
илиç
(U+00E7
)U+0301
или ḉ (U+1E09
). Для этого вам необходимо выполнить проверку в нормализованной форме:источник
perl6
, тоperl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
должны сделать все работы за вас.Быстрая альтернатива python2:
Пример:
источник