Sử dụng sed để loại bỏ cả dấu ngoặc vuông mở và đóng xung quanh chuỗi


18

Tôi đang chạy lệnh này trong shell bash trên Ubuntu 12.04.1 LTS. Tôi đang cố gắng loại bỏ cả nhân vật []nhân vật trong một cú trượt ngã, tức là không cần phải ống để quyến rũ lần thứ hai.

Tôi biết dấu ngoặc vuông có ý nghĩa đặc biệt trong biểu thức chính quy vì vậy tôi thoát khỏi chúng bằng cách thêm dấu gạch chéo ngược. Kết quả tôi mong đợi chỉ là chuỗi 123nhưng dấu ngoặc vuông vẫn còn và tôi muốn biết tại sao!

~$ echo '[123]' | sed 's/[\[\]]//'
[123]

Điều tôi đang cố gắng đạt được cuối cùng là gán bất cứ thứ gì giữa dấu ngoặc vuông cho biến bash để sử dụng ở nơi khác trong tập lệnh bash của tôi, vì vậy nếu có cách nào tốt hơn để đạt được điều đó (bằng cách sử dụng awk, có thể?), Hãy cho tôi biết .
Xhantar

2
Chỉ cần thêm dưới dạng nhận xét: Bạn có thể sử dụng tính năng PE của bash như trong: str='[123]'; str1=${str/\[/}; str2=${str1/\]}; echo $str2
Valentin Bajrami

1
@ val0x00ff - Thay thế bash thuần túy .. cảm ơn! :) Đã học được điều gì đó mới.
Xhantar

Câu trả lời:


23

Điều này thật dễ dàng, nếu bạn làm theo hướng dẫn cẩn thận: tất cả các thành viên trong một lớp nhân vật sẽ mất ý nghĩa đặc biệt (với một vài ngoại lệ). Và] mất ý nghĩa đặc biệt của nó nếu nó được đặt đầu tiên trong danh sách. Thử:

$ echo '[123]' | sed 's/[][]//g'
123
$

Điều này nói rằng:

  1. bên trong [ngoặc] bên ngoài , thay thế bất kỳ ký tự nào được bao gồm, cụ thể là:
    • ]
    • [
  2. thay thế bất kỳ trong số chúng bằng chuỗi rỗng - do đó chuỗi thay thế trống //,
  3. thay thế chúng ở khắp mọi nơi ( trên toàn cầu ) - do đó là trận chung kết g.

Một lần nữa, ] phải là người đầu tiên trong lớp bất cứ khi nào nó được bao gồm.


11

Tôi không chắc tại sao nó không hoạt động nhưng điều này không:

echo '[123]' | sed 's/\(\[\|\]\)//g'

hoặc này:

echo '[123]' | sed -r 's/(\[|\])//g'

Bạn cũng có thể thử một cách tiếp cận khác và khớp chuỗi bên trong ngoặc (giả sử chuỗi có thể được khớp dễ dàng và không được xác định bởi dấu ngoặc):

echo '[123]' | egrep -o "[0-9]+"

Tôi đang gặp rắc rối tương tự với regex ban đầu của bạn khi sử dụng grepnên tôi nghi ngờ đây không chỉ là một sedvấn đề.

Thật kỳ lạ, những kết quả này tạo ra kết quả khác nhau nhưng một trong số chúng phù hợp với những gì bạn muốn:

echo '[123]' | egrep -o '[^][]+'
123

echo '[123]' | egrep -o '[^[]]+'
3]

Áp dụng điều này cho bản gốc của bạn sed(và thêm công cụ /gsửa đổi để loại bỏ cả hai dấu ngoặc):

echo '[123]' | sed 's/[][]//g'
123

Cách tiếp cận thứ 3 của bạn (egrep -o ...) có vẻ như là giải pháp sạch nhất cho vấn đề của tôi. Tôi sẽ chỉ bao giờ có số nguyên ở giữa dấu ngoặc vuông (và xin lỗi, tôi nên đã đề cập đến điều đó trong câu hỏi của tôi) vì vậy tôi không nên gặp phải bất kỳ sự kỳ quặc nào tôi nghĩ. Cảm ơn!
Xhantar

3
Bạn cũng có thể sử dụng tr: echo '[123]' | tr -d '[]'- tránh nhầm lẫn regrec về việc trốn thoát.
James O'Gorman

@James O'Gorman - Thú vị. Vì một số lý do, tôi nghĩ rằng trchỉ có thể dịch tối đa một ký tự một lần, nhưng tôi đã nhầm. Cảm ơn!
Xhantar

4

Để xóa mọi thứ trước và sau dấu ngoặc:

$ echo '[123]' | sed 's/.*\[//;s/\].*//;'
123

Nếu dữ liệu của bạn như thế này luôn có nghĩa là bắt đầu và kết thúc bằng dấu ngoặc vuông:

$ echo '[123]' | sed 's/.//;s/.$//;'
123

Dữ liệu tôi đang làm việc sẽ luôn bắt đầu và kết thúc bằng dấu ngoặc vuông có. Tôi vẫn muốn biết lý do tại sao giải pháp của tôi không hoạt động. Có ý kiến ​​gì không? Và có cách nào để làm điều này mà không chỉ định 2x regex không?
Xhantar

1
@Guru giải pháp này hoạt động với tôi và đối với Xhantar, Đây là một phản hồi thực sự muộn, nhưng những gì tôi có thể thấy từ mã của bạn và hướng dẫn Bash Beginners tại tldp.org, bạn đã cố gắng thực hiện nhiều tìm kiếm và thay thế, một cho '[' và cái khác cho ']' sẽ không hoạt động, để loại bỏ hai tìm kiếm khác nhau và thay thế bằng cách sử dụng ";" hoặc các tùy chọn -e. 's / <tìm kiếm> / <thay thế> / g; s / <search> / <thay thế> / g 'HOẶC sed -e' s / <tìm kiếm> / <thay thế> / g '-e' s / <tìm kiếm> / <thay thế> / g '
ArunMKumar

1

Nếu bạn có một chuỗi phức tạp hơn như 'abcdef [123] ghijk', bạn cũng có thể sử dụng lệnh bash nội bộ 'cắt' để chỉ trích xuất văn bản giữa các dấu ngoặc vuông:

$ echo 'abcdef[123]ghijk' | cut -d '[' -f 2 | cut -d ']' -f 1
123

1

Bạn có thể thoát khỏi khung mở bằng cách sử dụng \[. Đối với khung đóng cửa, sử dụng []].

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.