Câu trả lời:
POSIXly:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
Nó sẽ không hoạt động nếu dòng bắt đầu hoặc kết thúc bằng ký tự byte không hợp lệ, nếu bạn muốn bao gồm trường hợp đó, bạn có thể thêm LC_ALL=C
, mặc dù chỉ LC_ALL=C
hoạt động với dữ liệu ký tự một byte.
perl6
dường như là công cụ tốt nhất, nếu bạn có nó trong hộp của mình:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Mặc dù nó vẫn bóp nghẹt các ký tự không hợp lệ.
Lưu ý rằng perl6
sẽ thay đổi văn bản của bạn bằng cách chuyển nó NFC
thành dạng:
$ 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
Trong nội bộ, perl6
lưu trữ chuỗi NFG
dưới dạng (viết tắt Normalization Form Grapheme
), đây là perl6
cách được phát minh để đối phó với các biểu đồ chưa được phân tách đúng cách:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6
sẽ thay đổi văn bản mặc dù (chuyển nó thành NFC (dạng chuẩn hóa "sáng tác")).
perl6
được lưu trữ ở NFG
dạng ( G
for Grapheme
), đó là perl6
cách để đối phó với các biểu đồ không được phân tách đúng.
Không phải grep mà là awk:
awk -F "" 'NF && $1 == $NF'
Những trường hợp đặc biệt được xử lý:
Một FS trống chia các bản ghi vào một ký tự cho mỗi lĩnh vực trong gawk
, mawk
và busybox
awk
(byte, không ký tự cho sau này hai), nhưng không phải là tiêu chuẩn và không làm việc trong hiện thực của awk
nguồn gốc từ một bản gốc bằng A, W và K như trên BSD và các đơn vị thương mại. Di động hơn nhưng nhiều hơn để gõ:
awk '/./ && substr($0,1,1) == substr($0,length)'
FS
vì chuỗi rỗng không phải là tiêu chuẩn và sẽ không hoạt động trong một số awk
triển khai.
awk 'length&&substr($0,1,1)==substr($0,length)'
(lưu ý đối số mặc định của length
là $0
, và hành động mặc định là {print $0}
)
nawk
gần như tồi tệ :-)
grep -xe '\(.\).*\1' -e .
Thí dụ:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-x
là cho trận đấu chính xác (trận đấu trên toàn bộ dòng). \1
là một tài liệu tham khảo ngược cho nhân vật bị bắt trong \(.\)
. Chúng tôi thêm một -e .
để chăm sóc trường hợp đặc biệt của một dòng chứa một ký tự đơn.
Nó giả sử đầu vào chứa văn bản hợp lệ trong ngôn ngữ hiện tại.
Trận đấu diễn ra trên ký tự , không phải byte (ví dụ, trong é trong UTF-8 là hai byte 0xc3 0xa9 chẳng hạn), cũng không phải cụm graphem (nó sẽ không hoạt động nếu những é đó được viết ở dạng phân tách của chúng e
theo sau là U + 0301 kết hợp giọng cấp tính chẳng hạn).
Để làm việc trên các cụm đồ thị, với một grep
hỗ trợ -P
cho PCRE:
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
Giả định rằng sự phân tách là giống nhau cho hai cụm, ví dụ, một ḉ
biểu thức c
U+0301
U+0327
sẽ không khớp với một biểu thức là c
U+0327
U+0301
hoặc ć
( U+0107
) U+0327
hoặc ç
( U+00E7
) U+0301
hoặc ( U+1E09
). Vì vậy, bạn cần thực hiện kiểm tra trên một biểu mẫu chuẩn hóa:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6
, sau đó perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
nên làm tất cả các công việc cho bạn.
Thay thế nhanh 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
Thí dụ:
$ 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$