Làm cách nào để xóa mọi thứ giữa hai ký tự với SED?


1

Làm cách nào để xóa tất cả văn bản GIỮA hai ký tự bằng cách sử dụng ...

Ví dụ:

00arbez+15611@hotmail.com
00aryapan+kee45j@rediffmail.com
asghrsha+hfcdedd@yahoo.com

Tôi muốn xóa văn bản + thành @ trong email. (Ngay cả dấu + cần phải bị xóa và ký hiệu @ cần giữ lại)

Tôi đã sử dụng lệnh sau:

sed -e 's/\(+\).*\(@\)/\1\2/' FILE.txt > RESULT.txt

Nhưng đầu ra của tệp bao gồm dấu "+" trong đó. Ví dụ: asghrsha+@yahoo.com

Tôi muốn đầu ra sau:

00arbez@hotmail.com
00aryapan@rediffmail.com
asghrsha@yahoo.com

Ai đó có thể giúp tôi sửa đổi lệnh sed ở trên không?

Câu trả lời:


3

Giải pháp đơn giản là ghép các (các) bạn muốn giữ xung quanh ranh giới của trận đấu và đặt chúng trở lại mà không có gì giữa chúng.

sed 's/+[^@+]*@/@/' FILE.txt >RESULT.txt

Bạn đã đặt lại những thứ bạn không muốn giữ, điều này rõ ràng tạo ra kết quả sai.

Bạn có thể nắm bắt chuỗi bạn muốn tiếp tục sử dụng \(... \)nhóm các dấu ngoặc đơn, nhưng trong trường hợp này, vì đó là một chuỗi hoàn toàn tĩnh, tôi đã chọn giữ chuỗi regex và chuỗi thay thế đơn giản nhất có thể và chỉ cần mã hóa cứng @như chuỗi thay thế .

Cũng lưu ý cách regex chú ý không đi ngang qua nhiều dấu cộng hoặc @dấu hiệu. Có lẽ bạn thực sự muốn dàn dựng bất kỳ +nhân vật lặp đi lặp lại thực sự; sau đó lấy ra điểm cộng từ lớp nhân vật phủ định, chỉ để lại [^@].


Có thể tránh CHIA SẺ trong tên tập tin của bạn quá.
tripleee

4

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 patternvà thay thế nó bằng replacement". /là dải phân cách ở đây.

Bạn pattern\(+\).*\(@\). 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 +*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\2sau 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 \1bở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ố sedngườ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.


1
Thật là một bước tốt đẹp từng bước giải thích. Kết quả cuối cùng thật bất ngờ.
Yoric

1
Giải thích tuyệt vời. Điều này giúp tôi rất nhiều để hiểu những gì đang xảy ra. Cảm ơn rất nhiều.
Joney Walker
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.