Trình chỉnh sửa luồng - Chuỗi
Lệnh thay thế
Các thao tác thay thế văn bản như "tìm và thay thế" rất phổ biến trong bất kỳ trình soạn thảo văn bản nào. Trong phần này, chúng tôi minh họa cách SED thực hiện thay thế văn bản. Dưới đây là cú pháp của lệnh thay thế.
[address1[,address2]]s/pattern/replacement/[flags]
Đây, address1 và address2lần lượt là địa chỉ bắt đầu và địa chỉ kết thúc, có thể là số dòng hoặc chuỗi mẫu. Cả hai địa chỉ này đều là tham số tùy chọn. Mẫu là văn bản mà chúng ta muốn thay thế bằng chuỗi thay thế. Ngoài ra, chúng tôi có thể chỉ định các cờ tùy chọn với SED.
Trong tệp books.txt, chúng tôi đã sử dụng dấu phẩy (,) để phân tách từng cột. Chúng ta hãy sử dụng thanh dọc (|) để tách từng cột. Để thực hiện việc này, hãy thay thế dấu phẩy (,) bằng thanh dọc (|).
[jerry]$ sed 's/,/ | /' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
1) A Storm of Swords | George R. R. Martin, 1216
2) The Two Towers | J. R. R. Tolkien, 352
3) The Alchemist | Paulo Coelho, 197
4) The Fellowship of the Ring | J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho, 288
6) A Game of Thrones | George R. R. Martin, 864
Nếu bạn quan sát kỹ thì chỉ có dấu phẩy đầu tiên được thay thế và dấu phẩy thứ hai vẫn như cũ. Tại sao? Ngay sau khi mẫu phù hợp, SED sẽ thay thế nó bằng chuỗi thay thế và chuyển sang dòng tiếp theo. Theo mặc định, nó chỉ thay thế lần xuất hiện đầu tiên. Để thay thế tất cả các lần xuất hiện, hãy sử dụng cờ toàn cầu (g) bằng SED như sau:
[jerry]$ sed 's/,/ | /g' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
1) A Storm of Swords | George R. R. Martin | 1216
2) The Two Towers | J. R. R. Tolkien | 352
3) The Alchemist | Paulo Coelho | 197
4) The Fellowship of the Ring | J. R. R. Tolkien | 432
5) The Pilgrimage | Paulo Coelho | 288
6) A Game of Thrones | George R. R. Martin | 864
Bây giờ tất cả các lần xuất hiện của dấu phẩy (,) được thay thế bằng thanh dọc (|).
Chúng tôi có thể hướng dẫn SED chỉ thực hiện thay thế văn bản khi khớp mẫu thành công. Ví dụ sau đây chỉ thay thế dấu phẩy (,) bằng dấu thanh dọc (|) khi một dòng chứa mẫu Hành hương.
[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho | 288
6) A Game of Thrones, George R. R. Martin, 864
Ngoài ra, SED có thể thay thế một trường hợp cụ thể của mô hình. Chúng ta hãy chỉ thay thế trường hợp thứ hai của dấu phẩy (,) bằng thanh dọc (|).
[jerry]$ sed 's/,/ | /2' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
1) A Storm of Swords, George R. R. Martin | 1216
2) The Two Towers, J. R. R. Tolkien | 352
3) The Alchemist, Paulo Coelho | 197
4) The Fellowship of the Ring, J. R. R. Tolkien | 432
5) The Pilgrimage,Paulo Coelho | 288
6) A Game of Thrones, George R. R. Martin | 864
Trong ví dụ trên, số ở cuối lệnh SED (hoặc ở vị trí của cờ) ngụ ý lần xuất hiện thứ hai.
SED cung cấp một tính năng thú vị. Sau khi thực hiện thay thế, SED cung cấp một tùy chọn để chỉ hiển thị các dòng đã thay đổi. Với mục đích này, SED sử dụngpcờ đề cập đến chữ in. Ví dụ sau chỉ liệt kê các dòng đã thay đổi.
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
Chúng tôi cũng có thể lưu trữ các dòng đã thay đổi trong một tệp khác. Để đạt được kết quả này, hãy sử dụngwcờ. Ví dụ sau đây cho thấy làm thế nào để làm điều đó.
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt
Chúng tôi đã sử dụng cùng một lệnh SED. Hãy để chúng tôi xác minh nội dung củajunk.txt tập tin.
[jerry]$ cat junk.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
Để thực hiện thay thế phân biệt chữ hoa chữ thường, hãy sử dụng cờ i ngụ ý bỏ qua chữ hoa chữ thường. Ví dụ sau thực hiện thay thế phân biệt chữ hoa chữ thường.
[jerry]$ sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
Cho đến nay, chúng ta chỉ sử dụng ký tự dấu gạch đầu (/) làm dấu phân cách, nhưng chúng ta cũng có thể sử dụng dấu thanh dọc (|), dấu (@), dấu mũ (^), dấu chấm than (!) Làm dấu phân cách. Ví dụ sau đây cho thấy cách sử dụng các ký tự khác làm dấu phân cách.
Hãy để chúng tôi giả sử bạn cần thay thế đường dẫn /bin/sed với /home/jerry/src/sed/sed-4.2.2/sed. Do đó, lệnh SED của bạn trông giống như sau:
[jerry]$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/jerry\/src\/sed\/sed-4.2.2\/sed/'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
/home/jerry/src/sed/sed-4.2.2/sed
Chúng ta có thể làm cho lệnh này dễ đọc và dễ hiểu hơn. Chúng ta hãy sử dụng thanh dọc (|) làm dấu phân cách và xem kết quả.
[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
/home/jerry/src/sed/sed-4.2.2/sed
Thật! Chúng tôi nhận được cùng một kết quả và cú pháp dễ đọc hơn. Tương tự, chúng ta có thể sử dụng dấu "at" (@) làm dấu phân cách như sau:
[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
/home/jerry/src/sed/sed-4.2.2/sed
Ngoài ra, chúng ta có thể sử dụng dấu mũ (^) làm dấu phân cách.
[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
/home/jerry/src/sed/sed-4.2.2/sed
Chúng ta cũng có thể sử dụng dấu chấm than (!) Làm dấu phân cách như sau:
[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
/home/jerry/src/sed/sed-4.2.2/sed
Nói chung, dấu gạch chéo ngược (/) được sử dụng làm dấu phân cách nhưng đôi khi sử dụng các dấu phân cách được hỗ trợ khác với SED sẽ thuận tiện hơn.
Tạo một chuỗi con
Chúng tôi đã học được lệnh thay thế mạnh mẽ. Hãy để chúng tôi xem liệu chúng tôi có thể tìm thấy một chuỗi con từ một văn bản phù hợp hay không. Hãy để chúng tôi hiểu cách thực hiện với sự trợ giúp của một ví dụ.
Chúng ta hãy xem xét văn bản sau:
[jerry]$ echo "Three One Two"
Giả sử chúng ta phải sắp xếp nó thành một dãy. Có nghĩa là, nó nên in Một trước, sau đó Hai, và cuối cùng là Ba. Một lớp lót sau đây không cần thiết.
echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'
Lưu ý rằng trong ví dụ trên, thanh dọc (|) được sử dụng làm dấu phân cách.
Trong SED, các chuỗi con có thể được chỉ định bằng cách sử dụng toán tử nhóm và nó phải được bắt đầu bằng một ký tự thoát, tức là, \( và \).
\wlà một biểu thức chính quy khớp với bất kỳ chữ cái, chữ số hoặc dấu gạch dưới nào và "+" được sử dụng để khớp với nhiều ký tự. Nói cách khác, biểu thức chính quy\(\w\+\) khớp với từ đơn từ chuỗi đầu vào.
Trong chuỗi đầu vào, có ba từ được phân tách bằng dấu cách, do đó có threecác biểu thức chính quy được phân tách bằng dấu cách. Biểu thức chính quy đầu tiên lưu trữ từ đầu tiên, tức là Ba, biểu thức thứ hai lưu trữ từOnevà thứ ba lưu trữ từ Two
Các chuỗi con này được giới thiệu bởi \N,với N là số chuỗi con. Vì thế,\2 in chuỗi con thứ hai, tức là, One; \3 in chuỗi con thứ ba, tức là, Two; và \1 in chuỗi con đầu tiên, tức là, Three
Hãy để chúng tôi phân tách các từ này bằng dấu phẩy (,) và sửa đổi biểu thức chính quy cho phù hợp.
[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
One,Two,Three
Lưu ý rằng bây giờ có dấu phẩy (,) thay vì dấu cách trong biểu thức chính quy.
Cờ thay thế chuỗi (chỉ GNU SED)
Trong phần trước, chúng ta đã xem một số ví dụ về lệnh thay thế. GNU SED cung cấp một số chuỗi thoát đặc biệt có thể được sử dụng trong chuỗi thay thế. Lưu ý rằng các cờ thay thế chuỗi này là dành riêng cho GNU và có thể không hoạt động với các biến thể khác của SED. Ở đây chúng ta sẽ thảo luận về các cờ thay thế chuỗi.
\ L: Khi \ L được chỉ định trong chuỗi thay thế, nó coi tất cả các ký tự còn lại của từ sau \ L là ký tự viết thường. Ví dụ: các ký tự "ULO" được coi là ký tự viết thường.
[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288
\ u: Khi \ u được chỉ định trong chuỗi thay thế, nó coi ký tự ngay sau \ u là ký tự viết hoa. Trong ví dụ sau, \ u được sử dụng trước các ký tự 'a' và 'o'. Do đó SED coi các ký tự này là chữ hoa.
[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, pAulO Coelho, 197
5) The Pilgrimage, pAulO Coelho, 288
\ U: Khi \ U được chỉ định trong chuỗi thay thế, nó coi tất cả các ký tự còn lại của từ sau \ U là ký tự viết hoa.
[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAULO Coelho, 197
5) The Pilgrimage, PAULO Coelho, 288
\ E: Cờ này nên được sử dụng với \ L hoặc \ U. Nó dừng chuyển đổi do cờ \ L hoặc \ U bắt đầu. Trong ví dụ sau, chỉ có từ đầu tiên được thay thế bằng các chữ cái viết hoa.
[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt
Khi thực thi đoạn mã trên, bạn nhận được kết quả sau:
3) The Alchemist, PAULO coelho, 197
5) The Pilgrimage, PAULO coelho, 288