Tôi sẽ bắt đầu với lệnh ban đầu thay vì xây dựng từ đầu. Xây dựng từ đầu là một cách tiếp cận tuyệt vời trong trường hợp này, vẫn có một giá trị giáo dục trong việc hiểu lệnh ban đầu và các bước bạn có thể thực hiện để điều chỉnh lệnh theo nhu cầu của mình.
Cốt lõi của lệnh gốc:
sed -e 's/\(+\).*\(@\)/\1\2/'
Biểu thức ở dạng s/pattern/replacement/
, có nghĩa là "tìm kiếm pattern
và thay thế nó bằng replacement
". /
là dải phân cách ở đây.
Bạn pattern
là \(+\).*\(@\)
. Chức năng khớp của nó sẽ giống nhau nếu có +.*@
(kèm theo một cái gì đó \( \)
có liên quan trong bối cảnh replacement
, chúng ta sẽ nhận được nó). Một mẫu +.*@
có nghĩa là "nghĩa đen +
theo sau (gần như) bất kỳ ký tự ( .
) nào được lặp lại từ 0 trở lên ( *
), theo sau là chữ @
".
Lưu ý +
phù hợp với khả năng đầu tiên +
và *
tham lam nên trận đấu này kéo dài từ lần đầu tiên +
đến lần cuối cùng @
. Nó có thể không quan trọng trong trường hợp cụ thể của bạn, đôi khi nó vẫn rất quan trọng.
Thay thế của bạn là \1\2
. Nó có nghĩa là "bất cứ thứ gì được khớp bởi thứ 1 \( \)
và theo sau là bất cứ thứ gì được khớp với thứ 2 \( \)
". Đầu tiên của bạn \( \)
là trên thực tế \(+\)
, nó phù hợp với +
bạn muốn thoát khỏi.
Để làm rõ: lý do các \( \)
nhóm này xuất hiện trong mẫu (vì vậy mẫu không chỉ +.*@
) là do chúng xác định các đoạn được gọi là \1
và \2
sau này.
Vì vậy, nếu bạn không muốn +
được in, thay đổi tối thiểu đối với lệnh ban đầu của bạn sẽ bị bỏ qua \1
, vì đây là phần chính xác in +
trong trường hợp của bạn.
sed -e 's/\(+\).*\(@\)/\2/'
Nhưng sau đó, bạn không cần \( \)
xung quanh +
trong mẫu, do đó bạn có thể đơn giản hóa:
sed -e 's/+.*\(@\)/\1/'
Lưu ý \2
đã trở thành \1
bởi vì \(@\)
bây giờ là \( \)
nhóm đầu tiên . Ngoài ra, vì nó chỉ có thể khớp @
, nên bạn có thể sử dụng nghĩa đen @
thay vì \1
:
sed -e 's/+.*\(@\)/@/'
Nhưng bây giờ bạn không cần \( \)
gì cả. Lệnh trở thành:
sed -e 's/+.*@/@/'
Sau đó, bạn nhớ lại *
là tham lam vì vậy .*
có thể bao gồm (thêm) +
hoặc / và @
. Giả sử bạn không muốn điều này. Bạn cần biến .
thành thứ gì đó phù hợp với bất cứ thứ gì ngoại trừ @
hoặc +
:
sed -e 's/+[^@+]*@/@/'
Đây chính xác là những gì câu trả lời khác này đã cho bạn. Một số sed
người dùng có kinh nghiệm sẽ xây dựng giải pháp này từ đầu. Như bạn có thể thấy có thể giảm lệnh ban đầu của mình, từng bước một cách hợp lý và đi đến cùng một giải pháp.