linux unix

Biểu thức chính quy là một chuỗi có thể được sử dụng để mô tả một số chuỗi ký tự. Biểu thức chính quy được sử dụng bởi một số lệnh Unix khác nhau, bao gồm ed , sed , awk , grep và ở một mức độ hạn chế hơn, vi .

Ở đây SED là viết tắt của s tream ed itor. Trình chỉnh sửa hướng luồng này được tạo riêng để thực thi các tập lệnh. Do đó, tất cả dữ liệu đầu vào mà bạn cấp vào nó sẽ đi qua và chuyển đến STDOUT và nó không thay đổi tệp đầu vào.

Mi sed

Trước khi bắt đầu, hãy đảm bảo rằng chúng tôi có một bản sao cục bộ của tệp văn bản / etc / passwd để làm việc với sed . Như đã đề cập trước đây, sed có thể được gọi bằng cách gửi dữ liệu thông qua một đường ống đến nó như sau:

$ cat /etc/passwd | sed
Usage: sed [OPTION]... {script-other-script} [input-file]...

-n, --quiet, --silent
suppress automatic printing of pattern space
-e script, --expression = script

Lệnh cat đưa nội dung của / etc / passwd để sed qua đường ống vào không gian mẫu của sed. Không gian mẫu là vùng đệm công việc bên trong mà sed sử dụng cho các hoạt động của nó.

Cú pháp chung sed

Sau đây là cú pháp chung cho sed –

/pattern/action

Ở đây, mẫu là một biểu thức chính quy và hành động là một trong các lệnh được đưa ra trong bảng sau. Nếu mẫu bị bỏ qua, hành động được thực hiện cho mọi dòng như chúng ta đã thấy ở trên.

Ký tự gạch chéo (/) bao quanh mẫu là bắt buộc vì chúng được sử dụng làm dấu phân cách.

Sr.No.Phạm vi & Mô tả
1P In dòng
2d Xóa dòng
3s / pattern1 / pattern2 / Thay thế lần xuất hiện đầu tiên của mẫu1 bằng mẫu2

Xóa tt c các dòng vi sed

Bây giờ chúng ta sẽ hiểu cách xóa tất cả các dòng bằng sed. Gọi lại sed; nhưng sed bây giờ được cho là sử dụng dòng lệnh xóa sửa , được ký hiệu bằng chữ cái d

$ cat /etc/passwd | sed 'd'
$

Thay vì gọi sed bằng cách gửi một tệp đến nó thông qua một đường ống, sed có thể được hướng dẫn để đọc dữ liệu từ một tệp, như trong ví dụ sau. Lệnh sau thực hiện giống hệt như trong ví dụ trước, không có lệnh cat

$ sed -e 'd' /etc/passwd
$

Địa ch sed

Sed cũng hỗ trợ địa chỉ. Địa chỉ là các vị trí cụ thể trong một tệp hoặc một phạm vi nơi một lệnh chỉnh sửa cụ thể sẽ được áp dụng. Khi sed gặp không có địa chỉ, nó thực hiện các hoạt động của nó trên mọi dòng trong tệp.

Lệnh sau đây thêm một địa chỉ cơ bản vào lệnh sed mà bạn đang sử dụng:

$ cat /etc/passwd | sed '1d' |more
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

Chú ý rằng số 1 được thêm vào trước lệnh xóa sửa . Điều này hướng dẫn sed thực hiện lệnh chỉnh sửa trên dòng đầu tiên của tệp. Trong ví dụ này, sed sẽ xóa dòng đầu tiên của / etc / password và in phần còn lại của tệp.

Dãy địa ch sed

Bây giờ chúng ta sẽ hiểu cách làm việc với các dải địa chỉ sed . Vì vậy, điều gì sẽ xảy ra nếu bạn muốn xóa nhiều hơn một dòng khỏi một tệp? Bạn có thể chỉ định một dải địa chỉ với sed như sau:

$ cat /etc/passwd | sed '1, 5d' |more
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

Lệnh trên sẽ được áp dụng trên tất cả các dòng bắt đầu từ 1 đến 5. Thao tác này sẽ xóa năm dòng đầu tiên.

Hãy thử các dải địa chỉ sau:

Sr.No.Phạm vi & Mô tả
1‘4,10 ngày’ Các dòng bắt đầu từ ngày 4 đến ngày 10 sẽ bị xóa
2’10 .4 ngày’ Chỉ có dòng thứ 10 bị xóa, vì sed không hoạt động theo hướng ngược lại
3‘4, + 5 ngày’ Điều này khớp với dòng 4 trong tệp, xóa dòng đó, tiếp tục xóa năm dòng tiếp theo, sau đó ngừng xóa và in phần còn lại
4‘2,5! D’ Thao tác này sẽ xóa mọi thứ ngoại trừ bắt đầu từ dòng thứ 2 đến dòng thứ 5
5‘1 ~ 3d’ Thao tác này sẽ xóa dòng đầu tiên, bước qua ba dòng tiếp theo, rồi xóa dòng thứ tư. Sed tiếp tục áp dụng mẫu này cho đến khi kết thúc tệp.
6‘2 ~ 2ngày’ Điều này yêu cầu sed xóa dòng thứ hai, bước qua dòng tiếp theo, xóa dòng tiếp theo và lặp lại cho đến khi đạt đến cuối tệp
7‘4,10p’ Các dòng bắt đầu từ ngày 4 đến ngày 10 được in
số 8‘4, d’ Điều này tạo ra lỗi cú pháp
9’10ngày’ Điều này cũng sẽ tạo ra lỗi cú pháp

Lưu ý – Trong khi sử dụng hành động p , bạn nên sử dụng tùy chọn -n để tránh in dòng lặp lại. Kiểm tra sự khác biệt giữa hai lệnh sau:

$ cat /etc/passwd | sed -n '1,3p'
Check the above command without -n as follows −
$ cat /etc/passwd | sed '1,3p'

Lnh thay thế

Lệnh thay thế, ký hiệu là s , sẽ thay thế bất kỳ chuỗi nào bạn chỉ định bằng bất kỳ chuỗi nào khác mà bạn chỉ định.

Để thay thế một chuỗi này bằng một chuỗi khác, sed cần có thông tin về nơi chuỗi đầu tiên kết thúc và chuỗi thay thế bắt đầu. Đối với điều này, chúng tôi tiến hành liên kết hai chuỗi bằng ký tự dấu gạch chéo ( / ).

Lệnh sau thay thế lần xuất hiện đầu tiên trên một dòng của gốc chuỗi bằng chuỗi amrood .

$ cat /etc/passwd | sed 's/root/amrood/'
amrood:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Điều rất quan trọng cần lưu ý là sed chỉ thay thế cho lần xuất hiện đầu tiên trên một dòng. Nếu gốc chuỗi xuất hiện nhiều hơn một lần trên một dòng thì chỉ so khớp đầu tiên sẽ được thay thế.

Để sed thực hiện thay thế toàn cục, hãy thêm ký tự g vào cuối lệnh như sau:

$ cat /etc/passwd | sed 's/root/amrood/g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh

C thay thế

Có một số cờ hữu ích khác có thể được chuyển ngoài cờ g và bạn có thể chỉ định nhiều cờ cùng một lúc.

Sr.No.Cờ & Mô tả
1g Thay thế tất cả các trận đấu, không chỉ trận đấu đầu tiên
2CON SỐ Chỉ thay thế trận đấu thứ NUMBER
3P Nếu thay thế được thực hiện, sau đó in không gian mẫu
4w FILENAME Nếu thay thế được thực hiện, sau đó ghi kết quả vào FILENAME
5Tôi hoặc tôi Đối sánh theo cách không phân biệt chữ hoa chữ thường
6M hoặc m Ngoài hành vi bình thường của các ký tự biểu thức chính quy đặc biệt ^ và $, cờ này khiến ^ khớp với chuỗi trống sau một dòng mới và $ khớp với chuỗi trống trước một dòng mới

S dng du phân tách chui thay thế

Giả sử bạn phải thực hiện thay thế trên một chuỗi bao gồm ký tự gạch chéo về phía trước. Trong trường hợp này, bạn có thể chỉ định một dấu phân tách khác bằng cách cung cấp ký tự được chỉ định sau ký tự s .

$ cat /etc/passwd | sed 's:/root:/amrood:g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Trong ví dụ trên, chúng tôi đã sử dụng : làm dấu phân tách thay vì dấu gạch chéo / vì chúng tôi đang cố gắng tìm kiếm / root thay vì gốc đơn giản.

Thay thế bng Không gian trng

Sử dụng một chuỗi thay thế trống để xóa hoàn toàn chuỗi gốc khỏi tệp / etc / passwd –

$ cat /etc/passwd | sed 's/root//g'
:x:0:0::/:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Thay thế địa ch

Nếu bạn muốn thay thế chuỗi sh bằng chuỗi im lặng chỉ trên dòng 10, bạn có thể chỉ định nó như sau:

$ cat /etc/passwd | sed '10s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/quiet

Tương tự, để thay thế dải địa chỉ, bạn có thể làm như sau:

$ cat /etc/passwd | sed '1,5s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/quiet
daemon:x:1:1:daemon:/usr/sbin:/bin/quiet
bin:x:2:2:bin:/bin:/bin/quiet
sys:x:3:3:sys:/dev:/bin/quiet
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Như bạn có thể thấy từ đầu ra, năm dòng đầu tiên có chuỗi sh chuyển thành yên tĩnh , nhưng các dòng còn lại được giữ nguyên.

Lnh phù hp

Bạn sẽ sử dụng tùy chọn p cùng với tùy chọn -n để in tất cả các dòng phù hợp như sau:

$ cat testing | sed -n '/root/p'
root:x:0:0:root user:/root:/bin/sh
[root@ip-72-167-112-17 amrood]# vi testing
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

S dng Cm t Thông dng

Trong khi đối sánh các mẫu, bạn có thể sử dụng biểu thức chính quy để linh hoạt hơn. Kiểm tra ví dụ sau phù hợp với tất cả các dòng bắt đầu bằng daemon và sau đó xóa chúng

$ cat testing | sed '/^daemon/d'
root:x:0:0:root user:/root:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Sau đây là ví dụ xóa tất cả các dòng kết thúc bằng sh 

$ cat testing | sed '/sh$/d'
sync:x:4:65534:sync:/bin:/bin/sync

Bảng sau liệt kê bốn ký tự đặc biệt rất hữu ích trong biểu thức chính quy.

Sr.No.Nhân vật & Mô tả
1^ Khớp với đầu dòng
2$ Khớp với cuối dòng
3. Khớp với bất kỳ ký tự đơn nào
4* Khớp với không hoặc nhiều lần xuất hiện của ký tự trước đó
5[ký tự] So khớp bất kỳ một trong các ký tự được cho trong ký tự, trong đó ký tự là một chuỗi ký tự. Bạn có thể sử dụng ký tự – để chỉ ra một loạt các ký tự.

Nhân vt phù hp

Hãy xem thêm một vài biểu thức để chứng minh việc sử dụng siêu ký tự . Ví dụ, mẫu sau:

Sr.No.Biểu thức & Mô tả
1/AC/ Khớp các dòng có chứa các chuỗi như a + c , ac , abc , match và a3c
2/AC/ Khớp các chuỗi tương tự với các chuỗi như ace , yacc và Arctic
3/ [tT] anh ấy / Đối sánh chuỗi The và
4/ ^ $ / Khớp các dòng trống
5/^.*$/ Khớp toàn bộ dòng bất kể nó là gì
6/ * / Khớp một hoặc nhiều khoảng trắng
7/ ^ $ / Khớp các dòng trống

Bảng sau đây cho thấy một số bộ ký tự được sử dụng thường xuyên:

Sr.No.Đặt & Mô tả
1[az] Khớp một chữ cái thường
2[AZ] Khớp một chữ hoa đơn lẻ
3[a-zA-Z] Khớp một chữ cái
4[0-9] Khớp một số
5[a-zA-Z0-9] Khớp một chữ cái hoặc một số

T khóa lp nhân vt

Một số từ khóa đặc biệt thường có sẵn cho regexps , đặc biệt là các tiện ích GNU sử dụng regexps . Chúng rất hữu ích cho các biểu thức chính quy sed vì chúng đơn giản hóa mọi thứ và nâng cao khả năng đọc.

Ví dụ: các ký tự từ a đến z và các ký tự từ A đến Z , tạo thành một lớp ký tự có từ khóa [[: alpha:]] Sử dụng từ khóa lớp ký tự bảng chữ cái, lệnh này chỉ in những dòng trong tệp /etc/syslog.conf bắt đầu bằng một chữ cái trong bảng chữ cái –

$ cat /etc/syslog.conf | sed -n '/^[[:alpha:]]/p'
authpriv.* /var/log/secure
mail.* -/var/log/maillog
cron.* /var/log/cron
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log

Bảng sau đây là danh sách đầy đủ các từ khóa lớp ký tự có sẵn trong GNU sed.

Sr.No.Lớp nhân vật & Mô tả
1[[: alnum:]] Chữ và số [az AZ 0-9]
2[[: alpha:]] Bảng chữ cái [az AZ]
3[[:trống:]] Ký tự trống (dấu cách hoặc tab)
4[[: cntrl:]] Kiểm soát các ký tự
5[[: chữ số:]] Các số [0-9]
6[[: graph:]] Bất kỳ ký tự hiển thị nào (không bao gồm khoảng trắng)
7[[:thấp hơn:]] Chữ thường [az]
số 8[[:in:]] Các ký tự có thể in được (ký tự không điều khiển)
9[[:điểm:]] Các ký tự dấu câu
10[[:không gian:]] Khoảng trắng
11[[:phía trên:]] Chữ hoa [AZ]
12[[: xdigit:]] Chữ số thập lục phân [0-9 af AF]

Aampersand References

Siêu ký tự sed & đại diện cho nội dung của mẫu đã khớp. Ví dụ: giả sử bạn có một tệp có tên phone.txt chứa đầy các số điện thoại, chẳng hạn như sau:

5555551212
5555551213
5555551214
6665551215
6665551216
7775551217

Bạn muốn đặt mã vùng (ba chữ số đầu tiên) được bao quanh bởi dấu ngoặc đơn để dễ đọc hơn. Để thực hiện việc này, bạn có thể sử dụng ký tự thay thế và ký tự –

$ sed -e 's/^[[:digit:]][[:digit:]][[:digit:]]/(&)/g' phone.txt
(555)5551212
(555)5551213
(555)5551214
(666)5551215
 
(666)5551216
(777)5551217

Ở đây trong phần mẫu, bạn đang khớp 3 chữ số đầu tiên và sau đó sử dụng & bạn đang thay thế 3 chữ số đó bằng các dấu ngoặc đơn xung quanh .

S dng nhiu lnh sed

Bạn có thể sử dụng nhiều lệnh sed trong một lệnh sed như sau:

$ sed -e 'command1' -e 'command2' ... -e 'commandN' files

Ở đây command1 đến commandN là các lệnh sed thuộc kiểu đã được thảo luận trước đó. Các lệnh này được áp dụng cho từng dòng trong danh sách các tệp do tệp đưa ra.

Sử dụng cơ chế tương tự, chúng ta có thể viết ví dụ về số điện thoại ở trên như sau:

$ sed -e 's/^[[:digit:]]\{3\}/(&)/g' \
-e 's/)[[:digit:]]\{3\}/&-/g' phone.txt
(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217

Lưu ý – Trong ví dụ trên, thay vì lặp lại từ khóa lớp ký tự [[: digit:]] ba lần, chúng tôi thay thế nó bằng \ {3 \} , có nghĩa là biểu thức chính quy đứng trước được so khớp ba lần. Chúng tôi cũng đã sử dụng \ để đưa ra ngắt dòng và điều này phải được loại bỏ trước khi lệnh được chạy.

Tài liu tham kho quay li

Ký hiệu và siêu ký tự là hữu ích, nhưng thậm chí còn hữu ích hơn là khả năng xác định các vùng cụ thể trong biểu thức chính quy. Các vùng đặc biệt này có thể được sử dụng làm tham chiếu trong chuỗi thay thế của bạn. Bằng cách xác định các phần cụ thể của một biểu thức chính quy, sau đó bạn có thể tham chiếu lại các phần đó bằng một ký tự tham chiếu đặc biệt.

Để thực hiện lại các tham chiếu , trước tiên bạn phải xác định một vùng và sau đó tham chiếu lại vùng đó. Để xác định một khu vực, bạn chèn các dấu ngoặc đơn gạch chéo ngược xung quanh mỗi khu vực quan tâm. Vùng đầu tiên mà bạn bao quanh bằng dấu gạch chéo ngược sau đó được tham chiếu bởi \ 1 , vùng thứ hai bởi \ 2 , v.v.

Giả sử phone.txt có văn bản sau:

(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217

Hãy thử lệnh sau:

$ cat phone.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/Area \
code: \1 Second: \2 Third: \3/'
Area code: (555) Second: 555- Third: 1212
Area code: (555) Second: 555- Third: 1213
Area code: (555) Second: 555- Third: 1214
Area code: (666) Second: 555- Third: 1215
Area code: (666) Second: 555- Third: 1216
Area code: (777) Second: 555- Third: 1217

Lưu ý – Trong ví dụ trên, mỗi biểu thức chính quy bên trong dấu ngoặc đơn sẽ được tham chiếu trở lại bởi \ 1 , \ 2 , v.v. Chúng tôi đã sử dụng \ để ngắt dòng ở đây. Điều này nên được loại bỏ trước khi chạy lệnh.

Để lại một bình luận