Я хочу знать, как использовать grepдля отображения всех строк, которые начинаются и заканчиваются одним и тем же символом.
Я хочу знать, как использовать grepдля отображения всех строк, которые начинаются и заканчиваются одним и тем же символом.
Ответы:
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 in NFGform ( Gfor Grapheme), что позволяет perl6правильно обрабатывать нескомпонованные графемы.
Не grep, а awk:
awk -F "" 'NF && $1 == $NF'
Эти особые случаи обрабатываются:
Пустой FS разделяет запись на один символ на поле в gawk, mawkи busybox awk(байты, а не символы для последних двух), но не является стандартным и не работает в реализациях, awkпроизводных от исходного A, W и K, как на BSDs и коммерческих единицах. Более портативный, но больше для ввода:
awk '/./ && substr($0,1,1) == substr($0,length)'
FSпустая строка не является стандартной и не будет работать в некоторых awkреализациях.
awk 'length&&substr($0,1,1)==substr($0,length)'(обратите внимание, что по умолчанию используется аргумент lengthis $0, а действие по умолчанию is {print $0})
nawkпочти так же плохо :-)
grep -xe '\(.\).*\1' -e .
Пример:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-xдля точного соответствия (совпадение по всей строке). \1являясь обратной ссылкой на персонажа, захваченного в \(.\). Мы добавляем a, -e .чтобы позаботиться о специальном случае строки, содержащей один единственный символ.
Предполагается, что ввод содержит действительный текст в текущей локали.
Соответствие идет по символу , а не по байту (например, é в UTF-8 - это два байта 0xc3 0xa9), или кластер graphem (он не будет работать, если эти é были записаны в разложенном виде с eпоследующим U + 0301 например, сочетая острый акцент).
Для работы на кластерах графема с grepподдержкой -PPCRE:
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
При этом предполагается, что разложение является одинаковым для двух кластеров, например, ḉвыражение, c U+0301 U+0327которое не соответствует, выражается как c U+0327 U+0301или ć( U+0107) U+0327или ç( U+00E7) U+0301или ḉ ( U+1E09). Для этого вам необходимо выполнить проверку в нормализованной форме:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6, то perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'должны сделать все работы за вас.
Быстрая альтернатива python2:
python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt
Пример:
$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt | cat -A
nathan$
ookie $
a line a$