Khớp mẫu loại trừ các ký tự trùng lặp


7

Có một biểu thức chính quy cho các ký tự sau khớp với các ký tự trong một bộ ký tự nhưng chỉ một lần không? Nói cách khác, một khi tìm thấy một ký tự, hãy xóa nó khỏi tập hợp.

Nếu grep không thể làm điều này, có tiện ích tích hợp nào có thể không?

Thí dụ:

Characters to match only once:   spine

Đầu vào:

spine
spines
spin
pine
seep 
spins

Đầu ra:

spine
spin
pine

EDIT:
Có nhiều cách để đạt được đầu ra này (một ví dụ dưới đây), nhưng tôi đang tìm cách để làm điều này mà không phải tùy chỉnh lệnh cho từng mẫu tôi muốn khớp.

grep '[spine]' input_file | grep -v 's.*s' | ... | grep -v 'e.*e'


Câu hỏi: Ứng dụng này là gì?
mdpc

Câu trả lời:


4

Với các biểu thức chính quy theo nghĩa toán học, điều đó là có thể, nhưng kích thước của các biểu thức chính quy tăng theo cấp số nhân so với kích thước của bảng chữ cái, vì vậy nó không thực tế.

Có một cách đơn giản với phủ định và backreferences .

grep '[spine]' | grep -Ev '([spine]).*\1'

Đầu tiên grepchọn các dòng có chứa ít nhất một trong số đó einps; dòng thứ hai greptừ chối các dòng chứa nhiều hơn một trong số bất kỳ (ví dụ cho phép spinal tapspendkhông foobarhoặc see).


1

Lấy cảm hứng từ biểu hiện của bạn, tôi có thể đưa ra một cái ngắn hơn, sử dụng egrep:

egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE

tương đương với

sed /s.*s/d;/p.*p/d;/i.*i/d;/n.*n/d;/e.*e/d; FILE

Và đây là cách tự động tạo lệnh sed từ đầu vào:

#!/bin/bash
word=$1
file=$2
expr=$(for c in $(echo $word | sed 's/./& /g'); do echo -n "/"$c".*"$c"/d;"; done);
sed $expr $file 

Tôi đã thử một cách tiếp cận tương tự với grep, nhưng không thể thuyết phục được shell lấy mẫu grep từ một biến, nhưng nếu tôi lặp lại nó và chèn kết quả bằng cắt và dán, lệnh đã hoạt động:

expr="'("$(for c in $(echo $wort | sed 's/./& /g'); do echo -n $c".*"$c"|"; done)

egrep -v ${expr/%|/)\'} FILE
# doesn't work, filters nothing, whole file is printed
# check:    
echo egrep -v $(echo $exp) FILE 
egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE
# manually: 
egrep -v '(s.*s|p.*p|i.*i|n.*n|e.*e)' FILE
spine
spin
pine

Có thể tôi đã mắc lỗi, có thể tôi mắc lỗi với việc mở rộng biến.


Xem bài viết đã chỉnh sửa của tôi cho đầu ra mong muốn. Ngoài ra, tôi đang tìm kiếm một giải pháp không yêu cầu một lệnh cụ thể phức tạp, tẻ nhạt.
Steven

Có, tôi thấy. Có lẽ tôi tìm cách tạo ra lệnh sed từ từ 'cột sống'.
người dùng không xác định

Cuối cùng tìm ra cách giải quyết nó với sed - điều đó có chấp nhận được không?
người dùng không xác định
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.