Các Lược Giảng Chuyên Sâu về Sử Dụng Văn Lệnh BASH trong Linux/Bài 4A

Từ Thư viện Khoa học VLOS
Bước tới: chuyển hướng, tìm kiếm

Loạt bài "Các Lược Giảng Chuyên Sâu về Sử Dụng Văn Lệnh BASH trong Linux" của tác giả Làng Đậu giữ bản quyền 2006. Người đọc chỉ được sử dụng cho mục đích học tập hay giảng dạy cho cá nhân. Cấm mọi hình thức sao chép, đăng lại, hay in lại nhằm mục đích mua bán hay trục lợi mà không có sự cho phép chính thức của tác giả. Mọi thông tin về việc phổ biến rộng rãi có tính quảng bá tài liệu này cho mục đích giáo dục hay các phê bình, đề nghị về nội dung bài giảng xin liên lạc về vo_quang_nhan@yahoo.com

Bài 4A : GNU C/C++, tác trình, lệnh sed

Sử dụng trình dịch GNU C/C++

Mở đầu

GNU C/C++ là một trình biên dịch được dùng phổ biến nhất trong Linux để phát triển các phần mềm. Có hai cú pháp cơ bản cho việc biên dịch đơn giản là

gcc [Tham_số ]:  Cho tất cả cá chương trình ngôn ngữ C
g++ [Tham_số ]:  Cho tất cả cá chương trình ngôn ngữ C++

Những tên mở rộng của các tập tên mã nguồn mà trình dịch GNU dùng mặc định là:

  • .c: của tập tin mã nguồn trong ngôn ngữ C: tiền xử lý, biên dịch, tạo tệp assemble
  • .C, .cc,cxx: của tập tin mã nguồn trong ngôn ngữ C++: tiền xử lý, biên dịch, tạo tệp assemble
  • .m: nguồn objective-C: tiền xử lý, biên dịch, tạo tệp assemble (hợp ngữ)
  • .i: tiền xử lý C; biên dịch sang hợp ngữ
  • .ii: tiền xử lý C++; biên dịch sang hợp ngữ
  • .s: mã assemble; hợp ngữ
  • .S: mã assemble; tiền xử lí, hợp ngữ
  • .h: tập tin tiền xử lí nhưng thường không được (hay không cần) sử dụng (gọi) trong dòng lệnh để dịch

Để đọc toàn bộ chi tiết, hãy gõ lệnh man gcc hay man g++.

Những tham số thông dụng trong trình dịch GNU

  • -x [ ngôn_ngữ [{{{2}}}]]: khai báo đặc biệt [ngôn_ngữ]  các các tập tin theo sau cho đến khi có tham số -x kế tiếp. Các giá trị của tham số ngôn ngữ là: c, objective-c, c-header, c++, cpp-output, assembler,và assembler-with-cpp. Nếu dùng tham số -x mà không có các giá trị ngôn ngữ đi kèm thì trình dịch sẽ bỏ qua tham số này
  • -c: dịch và tạo hợp ngữ cho tập tin mã nguồn nhưng không tiến hành liên kết (link). Do mặc định, tập tin đối tượng xuất ra sẽ có phần tên mở rộng là .o và có tên là tên của tập tin nguồn
  • -S: Ngừng sau khi biên dịch hợp lệ và tạo ra các tập tin hợp ngữ với tên mở rộng là .s thay cho .c hay .i'
  • -o [Tên_Tập_tin] : Xuất ra tập tin [Tên_Tập_tin] thay vì dùng tên mặc định (thường là a.out)

Thí dụ :

Contain of  first.C

#include "iostream.h" int main () { cout << "hello\n"; return 0; }

to compile and receive the output as hello: g++ first.C -o myhello

Alternately, we can compile it by separate the process into 2 stages:
g++ -c first.C (generate object file) g++ first.o -o myhello<BR
To run the myhello command #./myhello

the message should look like #hello

Các tham số quan trọng liên quan đến ngôn ngữ

  • -ansi: hỗ trợ toàn bộ chuẩn ANSI C;tắt các chức năng GNU mà có thể tạo xung đột với ANSI C như là các từ khoá asm, inline, và typeoff key words; tuy nhiên, các từ khoá thay thế như là __asm__, __extension__, __inline__, và __typeoff__ vẩn hữu hiệu
  • -fno-asm: không công nhận các từ khoá asm, inline, và typeoff. Thay vào đó, vẩn có thể dùng __asm__, __inline__, và __typeoff__ .
  • -fno-buildin: Không công nhận các hàm cho sẵn. Các hàm này bao gồm cả  ext, abort, abs, allocat, cos, exit, fabs, labs, memcmp, memcpy,sin, sqrt, strcmp,strcpy, và strlen
  • -funsigned-char: Đồng hoá kiểu char như là unsigned char.
  • -fsigned-char: Đồng hoá kiểu char như là signed char.
  • -funsigned-bitfields: cài các bit field như là không dấu (unsigned). Mặc định cho các bitfield là dấu.

Các tham số tiền xử lí quan trọng

  • -include [Tên_Tập_tin]: Xử lý tập tin [Tên_Tập_tin] như là tập tin nhập trước khi xử lí tập tin nhập thông thường. Tập tin [Tên_Tập_tin] sẽ được dịch đầu tiên.
  • -imacro [Tên_Tập_tin]: Xử lý tập tin [Tên_Tập_tin] như là tập tin nhập và loại bỏ thông báo tạo ra từ tập tin [Tên_Tập_tin] trước khi xử lí tập tin nhập thông thường. Điều này sẽ làm cho tất cả các macro được định nghiã trong tập tin [Tên_Tập_tin] có hiệu lực cho main.
  • -idirafter [Tên_Thư_Mục]: thêm thư mục [Tên_Thư_Mục] vào đường dẫn bao gồm thứ hai. Các thư mục của đường dẫn bao gồm thứ hai (second include path) sẽ được tìm kiếm mỗi khi có tập tin header không thể tìm thấy ở bất kì thư mục nào của các bao gồm chính (main include) . (Bao gồm chính có thể thêm vào bằng cách dùng tham số -I)

Các tham số quan trọng dùng trong liên kết

  • -l[Tên_Thư_Viện]: Dùng tên thư viện [Tên_Thư_Viện] khi tiến hành bước liên kết (linking). Bộ máy liên kết (linker) sẽ tìm trong các thư mục chuẩn tập tin thư viện có tên
lib[Tên_Thư_Viện].a
  • -static: không liên kết kiểu chia sẽ mà thay vào đó là dùng cách liên kết tĩnh. (Trong liên kết tĩnh các thư viện sẽ được chép lại và nối vào trong tập tin khi dịch ra do đó cõ tập tin xuất sẽ lớn hơn bình thường. Tuy nhiên, khi thực thi tập tin này sẽ không bị lệ thuộc vào sự tồn tại của các thư viện nữa --- vì nó đã có sẵn các du liệu thư viện này bên trong nội dung)

Thí dụ: Khi tạo ra một lệnh mount đặc biệt lệnh này sẽ không đòi hỏi các thư viện chia sẽ có thể tiện dùng trong các dĩa CD ROM Linux tự khởi động được (bootable CD ROM):

Content of file mountcd.c
#include <sys/mount.h>
int main (int argc, char ** argv)
{
   int dat=0;
   return mount(argv[1], argv[2], argv[3], MS_RDONLY | MS_MGC_VAL, &dat);
}

to compile use this command gcc -static mountcd.c -o mountcd

Tham số về thư mục thông dụng

  • -I[Tên_Thư_Mục] : thêm thư mục [Tên_Thư_Mục] vào trong danh sách các thư mục mà trình dịch sẽ tìm kiếm các tập tin bao gồm

Tham số cảnh cáo

  • -Wall: sử dụng mọi loại thông báo cảnh cáo; dùng tham số này sẽ rất có lợi cho việc thực tập viết mã trong C/C++

Tác trình và cách tạo tác trình

Khái niệm và đặc tính

Tác trình (daemon)  1 là các tiến trình chạy trong nền (background) nhằm thực hiện một thao tác hệ thống liên hệ. Khác với các module hay bộ điều vận, tác trình là chương trình riêng không phải là bộ phận của hạt nhân. Đa số các tác trình bắt đầu ở thời gian khởi động máy và tiếp tục tải cùng với thời gian hoạt động của máy. Một số tác trình khác chỉ chạy khi cần và có thể ngưng khi không cần thiết nữa. Trong khi một số tác trình có khả năng tương tác với nhiều chương trình liên quan thì số lớn các tác trình chỉ tương tác được với các chương trình viết riêng cho nó. Chẳng hạn như tác trình xinetd điều có ảnh hưởng một lúc đến nhiều chương trình như là ftp, talk, telnet,figner,vnc ... thì kbd là một tác trình đặc thù cho bàn phím trong X window.

So sánh với hệ thống Windows thì các tác trình có chức năng tương tự như các dịch vụ (service) hay các chương trình nằm ở thanh tác vụ (taskbar) của windows.

Một tác trình thường sau khi tải sẽ được giữ trong bộ nhớ và lắng nghe các yêu cầu từ các chương trình tương ứng để thực hiện các thao tác đòi hỏi hay trả lời cho các yêu cầu của chúng. Một số không ít các tác trình chỉ phục vụ cho một chương trình đặc trưng và thường sẽ bị kết thúc khi chương trình đó không họat động nữa

Tạo một tác trình trong C/C++

Hầu hết các tác trình đều dùng ngôn ngữ C hay C++ để tải chương trình vào bộ nhớ và chạy trong nền Sau đây là phần cốt lõi mã C mô tả:

Thí dụ:

//file name daemon.c
#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#define MAX_ARG 10 
int daemon_init(void); 

int main(int argc, char * argv[]) { daemon_init();<BR
[Khối_mã_thiết_lập_tác_trình]

return 0; }

int daemon_init(void) { pid_t pid; if ((pid = fork())<0) return(-1); //to create an independ process else if (pid != 0) exit (0); setsid(); //get an SID for it to avoid becoming an orphan process chdir("/"); umask(0); //close(STDIN_FILENO); //close(STDOUT_FILENO); //close(STDERR_FILENO);

return(0); }

Sau khi [Khối_mã_thiết_lập_tác_trình] bởi các dòng mã nguồn thích hợp, bạn có thể dịch thành daemon bằng lệnh sau:

gcc daemon.c -o myCdaemon

Lệnh trên sẽ tạo ra một tác trình có thể được gọi và tải trực tiếp. Tuy nhiên, để thấy rõ hoạt động của tác trình này, trong [Khối_mã_thiết_lập_tác_trình] có thể đặt vào đó vòng lặp để lắng nghe (hay đợi) trả lời cho một yêu cầu, hoặc có thể như bài tập, người lặp trình hãy thay bằng vòng lặp chỉ cần thi hành lệnh tạo mới tên 1 tập tin và đóng lại rồi thi hành lệnh sleep() trong vài giây.

Lưu ý:  

  • Tùy theo ý định sử dụng người lập trình có thể đóng các ngỏ xuất nhập chuẩn (nếu như không muốn cho tác trình đó liên lạc được với các ngỏ xuất nhập chuẩn này). Trong trường hợp chương trình cần nhiều tính bảo mật thì nên cứu xét tới việc đóng các thiết bị đó. 3 dòng màu cam được viết dạng bị chú trong đoạn mã trên mô tả các lệnh đóng chúng lại.
  • Một số hệ điều hành còn cung cấp những lệnhh đặt biệt để nâng một chương trình mệnh lệnh bất kì thành một tác trình như là lệnh startproc, start_daemon, checkproc tìm thấy trong các sản phẩm của SUSE. Phần mã trên cũng cho thấy cách để tạo mệnh lệnh trở thành tác trình
  • Các hệ điều hành mới còn hỗ trợ một hàm đặc biệt là daemon() . Hàm này hỗ trợ cho việc tạo một tác trình; rất tiện dụng nếu người viết chỉ dùng mã C/C++ để thiết lập tác trình. Hàm này đòi hỏi câu lệnh tiền xử lý #include <unistd.h>. Hãy dùng lệnh man daemon dể xem chi tiết cách sử dụng. việc thử nghiệm cách dùng này xem như bài tập

Tác trình truyền thống

Theo truyền thống thì các tác trình sẽ hỗ trợ ít nhất hai tham số tiêu chuẩn là start và stop. Tuy nhiên không có gì bắt buộc nguời tạo tác trình phải theo truyền thống đó nếu không có ý định dùng tác trình này trong các quá trình khởi động máy. Nhiều tác trình còn báo lỗi và không hoạt động nếu người gọi không xử dụng đến các tham số cho phép. Cú pháp chung để gọi một tác trình là:

[TÊN_TÁC_TRÌNH] [Tham_Số]

Sau đây là các [Tham_Số] thường thấy:

  • start: dùng để khởi động tác trình
  • stop: dùng để ngưng tác trình
  • restart: ngưng tác trình đang chạy nếu thành công thì lập tức khởi động lại nó
  • status: thông báo tình trạng hiện tại của tác trình

Rất nhiều tác trình thực sự bao gồm hai phần chính:

Phần mã nhị phân (mã máy) cốt lõi chỉ chứa lệnh vận hành là phần lệnh được mô tả trong A15.2 Phần bao gói bên ngoài (wrap). Phần này thường được viết bằng văn lệnh nhằm cung ứng hệ thống tham số chuẩn như kể trên và thực thi. Việc dùng văn lệnh để tạo phần bao gói sẽ được trinh bày sơ lược trong A15.4

Hầu hết các tác trình quan trọng của Linux được chứa trong thư mục /etc/init.d. Ban đầu tên của tác trình thường kết thúc bằng kí tự d (viết tắt từ chữ daemon) nhưng càng sau này truyền thống này ít còn được chấp hành.

Văn lệnh làm bao gói cho một tác trình

Thí dụ sau đây cho thấy cách để bao gói một tác trình tên là mydaemon. Tập tin bao gói này tên là myd.

#! /bin/sh
# Copyright (c) 1998-2001 ..... All rights reserved.
#
# Author: .... 
#
# /etc/init.d/myd

# implement this 2 lines if mydaemon use a configuration internal functions in 'mydconfig' #test -r /etc/sysconfig/mydconfig | exit 6 #. /etc/sysconfig/mydconfig

# 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - insufficient privilege # 5 - program is not installed # 6 - program is not configured # 7 - program is not running

DAEMON_NAME=<Full_name_of_Daemon> //place the full name of mydaemon here MYD_BIN="/usr/bin/init_daemon" //for SUSE use: MYD_BIN=/sbin/start_daemon test -x $MYD_BIN || exit 5

 #Implement specific OS function support here (ex ". /etc/rc.status" as in SUSE)

case "$1" in
start)
   #the daemon mydaemon is invoked only in this line
   echo -n "Starting mydaemon"
   ($MYD_BIN $DAEMON_NAME <Parameter_list>)  || return=7
   #please replace <Its_Parameter_list> by the properly arguments
;;
stop)
   echo -n "Shutting down mydaemon "
   kill $(pgrep $DAEMON_NAME) 
;;
restart)
   $0 stop && $0 start || return=1
;;
status)
   echo -n "Checking for service mydaemon: "
   # Status return:
   # 0 - service running
   # 1 - service dead, but /var/run/ pid file exists
   # 2 - service dead, but /var/lock/ lock file exists
   # 3 - service not running
   PS=`pgrep $MYD_BIN`
   if [ ! "$PS" = "" ]; then
      return=0
   else
      return=3
   fi
;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
   exit 1
esac
exit $?

Trong thí dụ trên, các dòng chữ màu cam cho thấy vị trí duy nhất mà mydaemon được gọi (trong dạng tên đầy đủ). Trong thực tế, tuỳ theo người lập trình kiến trúc cho tác trình của mình thì mẫu thí dụ trên có thể được điều chỉnh lại

Lưu ý:

Nếu dùng một daemon độc lập (như mô tả trong thí dụ 15.2 thì tất cả dòng màu cam nên được xóa đi và dòng màu cam

($MYD_BIN $DAEMON_NAME [Parameter_list])  || return=7  

được thay bằng dòng

([DAEMON_NAME] [Parameter_list]) || return 7

Trong đó, [DAEMON_NAME] [Parameter_list] là tên đầy đủ của tập tin tác trình và tham số cần gọi

/usr/bin/init_daemon 

là một lệnh có khả năng tải một lệnh khác bất kì trở thành một tác trình. Bước 2 trong A15.6 sẽ chỉ dẫn các tạo ra lệnh init_daemon này.

Tùy theo hệ điều hành có thể có hỗ trợ một số mệnh lệnh để việc thiết trí một văn lệnh bao gói được phù hợp! Tuy nhiên trong mọi trường hợp thì việc viết một văn lệnh đúng sẽ không bị từ chối khi được gọi.

Trong nhiều hệ điều hành thì biến MYD_BIN đã có sẵn tiện ích hỗ trợ như là lệnh start_daemon của SUSE người dùng không cần phải tạo ra lệnh init_daemon như trong mã thí dụ cho nghiã là chỉ cần viết thành MYD_BIN=/sbin/start_daemon.

Tác trình khởi động

Như đã đề cập, một số lớn tác trình bắt đầu tiến trình của nó trong lúc máy khởi động. Các tiến trình này được gọi tùy theo cấp độ khởi động và tùy theo thứ tự ưu tiên. Nguyên lý chung là các chương trình khởi động kể cả các tác trình (nếu cần) đều được tạo ra các liên kết mềm (softlink) trong các thư mục khởi động rc<n>.d, Trong đó, <n> có thể là một trong các cấp độ khởi động (0,1,2,3,4,5, 6 )  2 hay có giá trị S (S là chữ viết tắt của "single user"). Các liên kết này được đặt tên theo một luật rõ ràng:

Các tác trình được gọi trong quá trình máy bắt đầu chạy đều có tên bắt đầu bằng kí tự S Các tác trình được gọi trong quá trình bắt đầu tái khởi động hay ngưng (halt) máy đều có tên bắt đầu bằng chữ K. Thông thường, quá trình này dùng để ngưng các tác trình đã được chạy lúc khởi động máy

Hai kí tự kế tiếp xy (ở vị trí thứ nhì và ba) của tên chương trình khởi động tạo thành số nguyên bắt đầu từ 00 cho tới 99 . Con số này quy định thứ tự ưu tiên để trình khởi động nào được thi hành trước tiên. Số nhỏ hơn sẽ được gọi trước. (như vậy giữa S13abcd và S40abcd thì S13abcd sẽ có ưu tiên hơn và được thì hành trước S40abcd trong lúc khởi động) Các tác trình khởi động này khi được gọi sẽ tự động được nhận tham số start nếu nó có tên bắt đầu bằng kí tự S và tham số stop nếu kí tự này là K  3

ls -Al /etc/init.d/rc3.d
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 K03cron -> ../cron
lrwxrwxrwx 1 root root 10 2005-09-09 06:17 K05postfix -> ../postfix
lrwxrwxrwx 1 root root 8 2005-09-09 07:34 K05smbfs -> ../smbfs
lrwxrwxrwx 1 root root 8 2005-09-30 04:21 K06dhcpd -> ../dhcpd
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 K08slpd -> ../slpd
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 K16syslog -> ../syslog
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 K21random -> ../random
lrwxrwxrwx 1 root root 12 2005-09-12 07:03 K35mountdev -> ../mountdevd
..............
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 S01random -> ../random
lrwxrwxrwx 1 root root 9 2005-09-09 03:12 S06syslog -> ../syslog
lrwxrwxrwx 1 root root 17 2005-09-09 06:21 S12running-kernel -> ../running-kernel
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 S14slpd -> ../slpd
lrwxrwxrwx 1 root root 8 2005-09-30 04:21 S16dhcpd -> ../dhcpd
lrwxrwxrwx 1 root root 10 2005-09-09 06:17 S17postfix -> ../postfix
lrwxrwxrwx 1 root root 8 2005-09-09 07:34 S17smbfs -> ../smbfs
lrwxrwxrwx 1 root root 7 2005-09-09 06:17 S19cron -> ../cron
lrwxrwxrwx 1 root root 12 2005-09-12 07:02 S88moundev -> ../mountdevd
..................

Phần trích hiển thị trả về của lệnh ls cho thấy các softlink của các daemon. Hãy lưu ý cách đặt tên của các soflink này và thứ tự ưu tiên của chúng (bằng các số theo sau S và K)

Như vậy, để có thể tạo ra một tác trình sau khi đã được bao gói thì:

  1. Chép tập tin đó vào thư mục /etc/init.d (chẳng hạn đó là mydaemond). Đổi thuộc tính tập tin này sang +x.
  2. Chuyển thư mục hiện hoạt sang một trong các thư mục khởi động (thường là rc3.d )  4 (dùng lệnh cd )
  3. Tạo liên kết mềm S<xy>[TÊN_TÁC_TRÌNH] liên kết về mydaemond bằng lệnh: ls -s /etc/init.d/mydaemond S33mydaemon
  4. Tạo liên kết mềm K<mn>[TÊN_TÁC_TRÌNH] liên kết về mydaemond bằng lệnh: ls -s /etc/init.d/mydaemond K77mydaemon
  5. Tái khởi động máy hay gọi telinit để hoạt hoá các tác trình

Tạo tác trình khởi động với văn lệnh BASH

Để tạo một tác trình bằng văn lệnh có thể xem xét thí dụ sau đây như là khuôn mẫu ban đầu

  • Bước1: Viết tác trình bằng BASH hay bất kì dạng văn lệnh nào. chú ý tác trình chỉ có ý nghiã khi nó được tải và lưu lại trong bộ nhớ một cách bề vững, nên dó đó, trong phần lắp đặt có thể đặt vào đó một vòng lặp chạy trong tru kì lâu dài (hay vĩnh viễn cho tới khi bị tiêu hủy).

Thí dụ: thí dụ sau sẽ cập nhật thông tin 10 giây một lần vào tập tin /root/mydaemon.txt cho đến khi vượt quá 5000 giây sẽ tự hủy hay nếu bị gọi lệnh kill

  !#/bin/bash
   #file: mydaemon - 1st demonstration of daemon
   #
   MSG="/root/mydaemon.txt"
   cnt=0
   while [ $cnt -lt 500 ]; do
       echo "$0 $*" > $MSG  #write all parameter including name of the script into $MSG
       echo "value of counter: $cnt" >> $MSG  #append counter value
       let "cnt += 1"
      sleep 10   #delay 10 second after each refresh data file
   done
   exit

Sau khi viết xong dùng lệnh chmod +x mydaemon để thực thi hoá nó và thử chạy nó xem chương trình có bị lỗi hay không. (có thể gọi dạng ./mydaemon & để chạy thử nó trong nền) chứa tác trình thử nghiệm này trong thư mục /root.

  • Bước 2: Tạo một lệnh để đưa một chương trình trở thành tác trình dùng mã nguồn C: Thay [Khối_mã_thiết_lập_tác_trình] trong thí dụ 15.2 bằng khối mã cụ thể sau
Thí dụ:
i=0; 
switch (argc)
{
case 2:
    i=execlp(argv[1],argv[1],NULL);
    return(i);
case 3:
    i=execlp(argv[1],argv[1],argv[2],NULL);
    return(i);
case 4:
    i=execlp(argv[1],argv[1],argv[2],argv[3],NULL);
    return(i);
case 5:
    i=execlp(argv[1],argv[1],argv[2],argv[3],argv[4],NULL);
    return(i);
//you may wish to extend this switch command to support more argument calls for your  particular daemon
default:
    printf("too many paramter. System not support\n");
    return(-1);
}

Dùng lệnh : gcc daemon.c -o init_daemon để chuyển dịch nó sang mã nhị phân. Sau đó chép lệnh này vào thư mục /usr/bin để dùng cho mọi tác lệnh sau này. Có thể thử nghiệm lại sau khi dịch thành công bằng cách gõ câu lệnh ./init_daemon /root/mydaemon và sau đó dùng lệnh pgrep mydaemon parameter1 parameter2 để kiểm lại rằng mydaemon đã được tải thành công (lưu ý khi gọi lệnh init_daemon thì nhớ dùng tên đầy đủ của tập tin tác trình để làm tham số gọi). Nếu như không muốn tạo ra tác trình khởi động thì coi như bạn đã làm xong một tác trình thông thường

  • Bước 3: Tạo một gói bao cho tác trình mà bạn đã có và chép gói này vào thư mục /etc/init.d:

Thí dụ: Dùng mã sẵn có trong A15.3, thay các dòng màu cam bằng tên đúng của nó cụ thể là :

DAEMON_NAME=<Full_name_of_Daemon>  đổi thành
DAEMON_NAME=/root/mydaemon
$MYD_BIN $DAEMON_NAME <Its_Parameter_list>)  || return=7 đổi thành
($MYD_BIN $DAEMON_NAME 1 2;) || return 7

Chép tập tin myd này vào thư mục /etc/init.d. Nhớ dùng lệnh chmod +x /etc/init.d/myd để tạo đặc tính thực thì cho nó. Giờ có thể thư tải nó bằng cách gọi lệnh:

/etc/init.d/myd start

Dùng lệnh

pgrep mydaemon 

Để kiểm tra lại tác trình của bạn đã được tải và sau đó dùng lệnh

/etc/init.d stop

Và cũng dùng pgrep mydaemon để biết chắc tác trình mydaemon đã bi hủy

  • Bước 4: Tạo các liên kết mềm cho tác trình được tự động tải và dở tải khi máy chạy và tắt: Lựa chọn cấp khởi động n và thứ tự ưu tiên Sxy và Kmn

Thí dụ:  Cấp khởi động 3 và mn=xy=33; thi hành lệnh sau đây để tao liên kết mềm (dùng lệnh find để tìm ra vị trí của thư mục rc3.d)

find /etc -name rc3.d | xargs -i ln -s /etc/init.d/myd {}/S33myd
find /etc -name rc3.d | xargs -i ln -s /etc/init.d/myd {}/K33myd

Như vậy là hoàn tất một tác trình có khả năng tự khởi động

Sử dụng lệnh sed

Khái niệm

sed là lệnh có thể xem như là một chương trình thông dịch (intepreter) đơn giản dùng để soạn thảo dòng văn bản (streamline editor) không có tính tương tác (noninteractive). Vì sed có thể dùng trực tiếp và an toàn trên dòng lệnh một cách dể dàng nên nó thường được dùng trong các văn lệnh chung với các lệnh khác thông qua kĩ thuật ống dẫn truyền. sed sẽ hiển thị nội dung văn bản thay đổi theo dòng lên ngỏ ra chuẩn mà không làm thay đổi nội dung sẵn có của các tập tin.

Lưu ý Linux OS sử dụng phiên bản GNU của sed nên nó có nhiều hỗ trợ đặt thù cho phiên bản này và sẽ được xem như tiêu chuẩn trình bày trong phần phụ lục này

Các cú pháp thông dụng của sed là:

  • sed [Tham_Số] '[Chỉ_Thị]' [CÁC_TẬP_TIN_XỬ_LÝ]
  • sed [Tham_Số] -f [Tên_Tập_Chỉ_Thị_sed] [CÁC_TẬP_TIN_XỬ_LÝ]
  • sed [Tham_Số] -e '[Chỉ_Thị1]' -e '[Chỉ_Thị2]' -e '[Chỉ_Thị3]'... [CÁC_TẬP_TIN_XỬ_LÝ]

Lưu ý:

  • '[Chỉ_Thị]', '[Chỉ_Thị1]', '[Chỉ_Thị2]', '[Chỉ_Thị3]' ... là các chỉ thị soạn thảo mà sed hỗ trợ. Các chỉ thị này được đóng trong các dấu ngoặc dùng cho string ' (hay đôi khi dùng dấu " ) khi dùng trực tiếp qua dòng lệnh.
  • Khi dùng tham số -f [Tên_Tập_Chỉ_Thị_sed] thì các lệnh áp dụng của sed sẽ được viết vào trong một tập tin (mỗi hàng một mệnh lệnh) và các lệnh này sẽ được thi hành theo thứ tự từng lệnh một và áp dụng lên các dòng của [CÁC_TẬP_TIN_XỬ_LÝ].
  • Cũng như tham số -f, người ta có thể dùng dòng lệnh với nhiều tham số -e, theo sau mỗi tham số -e là một mệnh lệnh của tập tin [Tên_Tập_Chỉ_Thị_sed] theo thứ tự. Hiệu quả hoàn toàn tương đương nhau.

Thí dụ:

Tập tin mydat có nội dung như sau sẽ được sử dụng trong suốt phụ lục này
Joe         WA     Apple, mango          9
Mayer       TX     Orange,banana         7
Harry       AL     Peper, mango          4
Clara       UK     Peach, lemon          8
Holy        TX     Kiwi, pear            6
Smith       CA     Cherry, Smith's plum  10
Joesmith    CA     Apricot, lemon CA    3
Thomas      AZ     Banana, chili         6
CA          MA     Bean, apple           0

sed '3,6d' mydat  

là lệnh sẽ hiển thị mọi dòng của tập tin mydat ngoại trừ các dòng từ dòng thứ 3 đến dòng thứ 6. Tức là các dòng: (lệnh d viết tắt cho chữ delete nghiã là xoá bớt)

Joe         WA     mango                 9
Mayer       TX     orange,banana         6.5
Joesmith    CA     Appricot, lemon       3
Thomas      AZ     banana, chili         6

sed 's![Ss]mith!John! mydat

là lệnh thay thế dòng đầu tiên có chữ Smith hay chữ smith thành chữ John và hiển thị nội dung tập tin mydat ra. Như vậy khi hiển thị tập tin mydat, chỉ có dòng thứ 6 và 7 tại vị trí lần đầu tiên xuất hiện chữ chữ Smith sẽ bị đổi thành John (lệnh s viết tắt cho chữ substitute nghiã là thay thế)

John        CA     cherry, Smith's plum  10
JoeJohn     CA     Appricot, lemon       3

Các dòng khác hiển thị không đổi

sed -e 's/Joe/John/g' -e 's/CA/FL/g' 

là lệnh đổi tất cả các chữ Joe trong mỗi hàng thành John và tiếp tục thay tất cả các hàng ở mọi vị trí có chữ CA thành chữ FL. (trong lệnh s của sed, tham số g viết tắt cho chữ global nghiã là toàn bộ.)

Các tham số quan trọng

Ngoài hai tham số -e và -f các tham số sau đây của lệnh sed có thể hữu dụng

  • -n: không hiển thị ra stdout như mặc định. Như vậy để hiển thị các dòng xử lí thì người dùng có thể dùng lệnh p hay cờ hiệu p để hiển thị những gì cần thiết.
  • -r: Dùng biểu thức chính quy mở rộng trong các lệnh tìm kiếm thay vì dùng biểu thức chính quy thông thường

Thí dụ: Với tập tin mydat trong thí dụ bên trên

sed -n '2,4p' mydat  

sẽ chỉ hiển thị các dòng nội dung của tập tin từ dòng thứ 2 đến dòng thứ 4.

Các chỉ thị (lệnh) được sed hỗ trợ

Cấu trúc của một mệnh lệnh trong sed dạng :

[Vùng_Địa_chỉ][!][Lệnh][Tham_số]

Trong đó, [Vùng_Địa_chỉ], [!], [Tham_số] là các thành phần có thể vắng mặt còn thành phần [Lệnh] luôn luôn có mặt trong mọi câu lệnh sed.

[Vùng_Địa_chỉ] và [!]

  • [Vùng_Địa_chỉ]: Nếu không xuất hiện trong dòng lệnnh thì lệnh sed sẽ được áp dụng lên tất cả các dòng văn bản
  • Thành phần của [Vùng_Địa_chỉ]: Có thể ở trong các dạng cấu trúc
    1. [Dạng_thức] : Thoả mãn các quy ước trong Biểu thức chính quy và có thể hỗ trợ biểu thức chính quy mở rộng bằng cách thêm vào một số ý nghiã của siêu kí tự mới khi dùng tham số -r dể gọi sed. Thành phần kiểu này sẽ được đóng trong khuôn khổ của một cặp kí tự giới hạn. Một dùng để mở ngoặc chứa nội dung của <Dạng_thức> và một để đóng ngoặc lại. Kí tự giới hạn mặc định là /. Một khi người dùng muốn thay đổi giá trị mặc định này thì phải định nghiã lại. Việc định nghiã đơn giản chỉ việc dùng dấu \[Kí_tự_giới_hạn] cho việc mở ngoặc và không thêm bớt gì khi đóng ngoặc (tức là sẽ dùng cùng kí tự [Kí_tự_giới_hạn] nhưng không có dấu \ trước nó.
    2. [n] : dòng văn bản thứ n được chỉ định
    3. $ : dòng cuối cùng nhập từ ngỏ vào
    4. +[n] : xử lý cộng thêm <n> dòng văn bản chỉ có thể là thành phần thứ hai trong [Vùng_Địa_chỉ]  5
    5. ~[n] : xử lý tiếp cho đến khi thành phần thứ nhất trong [Vùng_Địa_chỉ] lặp lại [n] lần  5
  • Một [Vùng_Địa_chỉ] chứa một hoặc chứa tối đa hai thành phần mô tả trên mà được ngăn cách nhau bằng dấu phẩy (,):.
    1. Nếu [Vùng_Địa_chỉ] có duy nhất một thành phần thì sed chỉ thực thi <Lệnh> lên những dòng văn bản nào thoả mãn nội dung yêu cầu của thành phần
    2. Nếu [Vùng_Địa_chỉ] có hai thành phần (ngăn cách nhau bằng dấu phẩy) thì sed thực thi [Lệnh] lên những dòng văn bản bắt dầu từ dòng dầu tiên thoả mãn yêu cầu của thành phần thứ nhất và chấm dứt thực thi ở dòng văn bản nào thỏa mãn nội dung của thành phần thứ nhì (hoặc đến hết tập tin nếu không có dòng nào thoả mãn thành phần này)
  • Nếu [Vùng_Địa_chỉ] theo sau bởi dấu chấm than ! thì việc áp dụng lệnh sed sẽ đảo ngược hoàn toàn miền làm việc tức là nó chỉ áp dụng lên tất cả các dòng nằm ngoài  [Vùng_Địa_chỉ]
  • Theo mặc định thì từng dòng văn bản của ngỏ vào sẽ được xem xét nếu dòng đó tương hợp với [Vùng_Địa_chỉ] thì dòng đó sẽ được xử lí tiếp tục. Trong mục này, ta gọi dòng xử lý là các dòng văn bản thoả mãn được các điều kiện đòi hỏi của [Vùng_Địa_chỉ]

Thí dụ:

  • 2,4 vùng địa chỉ này chỉ cho phép xử lý lệnh sed trên các dòng từ 2 dến 4 của văn bản. Như vậy, lệnh
sed -n '2,4p' mydat

sẽ chỉ in ra từ nội dung của mydat các dòng 2,3 và 4.

  • xét thí dụ sau:
/ana/,5 

vùng địa chỉ này chỉ xử lí lệnh sed từ dòng văn bản nào bắt xuất hiện chữ May và ngưng xử lí kể từ sau dòng 5. Như vậy, lệnh

sed  '/ana/,5d' mydat

sẽ hiển thị tất cả các dòng ngoại trừ các dòng kể từ dòng thứ 2 (có nội dung phần tô màu cam

 Mayer       TX     orange,banana         6.5  

thoả mãn dạng thức /ana/) cho đến dòng thứ 5 (tức là các dòng 3,4, và 5 tiếp theo sau)

  • Vùng địa chỉ:
4   

chỉ xử lý dòng thứ 4. Như vậy, lệnh

sed '4i\-----Come from United Kingdom-------' mydat 

sẽ hiển thị toàn bộ mydat và có chèn thêm dòng -----Come from United Kingdom------- vào dòng thứ 4. (lệnh i viết tắt từ chữ insert)

  • Dùng !:
/Smith/! 

Sẽ xử lí tất cả các dòng ngoại trừ những dòng nào chứa chữ Smith. Như vậy, lệnh:

sed -n '\;Smith;!'p mydat
sẽ hiển thị toàn bộ nội dung mydat loại trừ dòng
  Smith       CA     cherry, Smith's plum  10


Lưu ý: trong thí dụ này chúng ta đã định nghiã dấu ; như là một kí tự giới hạn

Biểu thức chính quy trong sed

Hỗ trợ thông thường

Dùng siêu kí tự &

Đa số các lệnh đều liên quan đến việc tìm một dạng thức của dòng chữ nên sed hỗ trợ các siêu kí tự trong biểu thức chính quy thông thường và ngoài ra nó còn quy ước thêm một siêu kí tự có vị trí đặc biệt đó là dấu &.

Siêu kí tự & dùng để thay thế cho chuỗi kí tự của dòng văn bản nào tương hợp với dạng thức của biểu thức chính quy trong dòng văn bản đang đưọc xử lí. Điều này rất tiện lợi khi soạn thảo mà các dòng văn bản có nhiều đoạn thoả mãn dạng thức của biểu thức chính quy.

Thí dụ lệnh sau đây sẽ thay tất cả các từ apple bởi từ apple CA và các từ Apple bởi từ Apple CA. (xem lại dòng đầu tiên và dòng cuối cùng của mydat)

sed 's/[Aa]pple/& CA/g' mydat

Dùng cặp siêu kí tự \([Dạng_thức]\)

Trong truờng hợp muốn thay thế chỉ một bộ phận của biểu thức chính quy thì người lập trình có thể dùng đến cặp siêu kí tự \( \). Cặp siêu kí tự này có thể xuất hiện nhiều lần trong một biểu chức chính quy. Mỗi cặp như vậy sẽ đánh dấu một dạng thức con (được đóng trong cặp mở \( và đóng \) ngoặc) của biểu thức. Khi có dòng văn bản tương hợp được xử lí, thì: Nội dung chuỗi kí tự con của dòng văn bản tương hợp với \([Dạng_thức]\) đầu tiên sẽ được lưu giữ trong một bộ đệm kí hiệu là \1.

Nội dung chuỗi kí tự con của dòng văn bản tương hợp với \([Dạng_thức]\) thứ nhì sẽ được lưu giữ trong một bộ đệm kí hiệu là \2.

...

Có tối đa 9 bộ đệm để lưu giữ như trên (từ \1, \2, ...\9)

Thí dụ:

#content of mytext
This apple is a kind of American fruit
This mango is a kind of Asian fruit
This kiwi is a kind of African fruit 

sed 's/This \(.*\) is .* of \(.*\) fruit/\2 \1 is a kind of fruit/' mytext

Lệnh trên sẽ trả về kết quả là

American apple is a kind of fruit
Asian mango is a kind of fruit
African kiwi is a kind of fruit

Trong các dòng xử lí thì các chữ có màu cam được lưu giữ như là \1 còn chữ màu tím lưu giữ như là \2

Ngoài ra, sed còn hỗ trợ chế độ dùng Biểu thức chính quy mở rộng trong đó sử dụng thêm các siêu kí tự quy ước mới thông qua tham số -r

Bản hỗ trợ biểu thức chính quy mở rộng của sed -r

Ngoài các siêu kí tự trong biểu thức chính quy, khi dùng tham số -r, sed sẽ hỗ trợ thêm các siêu kí tự, quan trọng là:

Siêu
kí tự
Ý nghiã Thí dụ (RE) Tương hợp với Không tương hợp với
\b Biên giới của một từ \bfile\b ' file', ' file ' myfile, file1
\B Không là biên giới của một từ \Bfile  'myfile', 'file' ' file' '.file'
\w Kí tự là một chữ cái hay một chữ số  f\w*\.dat  file.dat, f1.dat, ...   f_.dat, f-i.dat
\W Kí tự không phải là chữ cái hay chữ số  file\W  tương đương với RE:
 file[^a-zA-Z0-9]
 f1, file
\r Kí tự xuống hàng (carriage return)
\d<xy> Kí tự có mã ASCII là <xy>
trong dạng thập phân
 dat\d97  tương đương với: data
 (mã ASCII của kí tự a là 97)
\o<xy> Kí tự có mã ASCII là <xy>
trong dạng bát phân
\x<xy> Kí tự có mã ASCII là <xy>
trong dạng thập lục phân

Các nhóm lệnh thông dụng của sed

Nhóm lệnh soạn thảo

Lệnh Chức năng Thí dụ (RE) Giải thích
a\<dòng_thêm_vào>
Chép nối dòng <Dòng_thêm_vào>
vào dòng đang xử lí
sed '/CA/a\Californian!' mydat Hiển thị các dòng trong mydat
nếu dòng có chữ CA thì chép nối
vào đó dòng chữ Californian!
c\<Dòng_thêm_vào>
Thay thế dòng hiện tại bằng <Dòng_thêm_vào> sed '/kiwi/c"erase kiwi line"' mydat Hiển thị các dòng trong mydat
nếu dòng nào có chữ kiwi
thì thay bằng "erase kiwi line"
i\<Dòng_thêm_vào>
Chèn <Dòng_thêm_vào>
vào trước hiện tại
sed '/CA/iHello' Hiển thị các dòng trong mydat
nếu là dòng có chữ CA thì
chèn vào trước đó dòng chữ Hello
d
Xóa (không hiển thị)
dòng hiện tại
sed '/\.txt$/d' Hiển thị danh mục tập tin trong
thư mục hiện hoạt
nhưng bỏ qua các tập tin kết thúc bằng .txt
s
Thay các dòng có dạng thức
bằng dòng khác
-- Xem chi tiết dưới đây
y
Chuyển dổi từng kí tự
theo ánh xạ xem
-- chi tiết dưới đây

Ghi chú về lệnh s

Đây là lệnh rất thông dụng có cú pháp:

s/[Dạng_thức]/[Dòng_thay_thế]/[Cờ_hiệu]

Lệnh này cho phép tìm ra các đoạn chuỗi kí tự trong dòng văn bản hiện tại thoả mãn [Dạng_thức]  và thay thế bằng [Dòng_thay_thế] trước khi hiển thị ta màn hình. Ở đây, khác với các lệnh tìm dòng trong [Vùng_Địa_chỉ] hay lệnh grep nhằm tìm ra dòng văn bản thoả mãn điều kiện tưong thích, lệnh s chỉ tập trung trên đoạn văn bản của dòng nào thoả màn điều kiện tìm kiếm và chỉ thay thế đoạn văn bản đó bằng [Dòng_thay_thế]

Không như các thành phần của [Vùng_Địa_chỉ], kí tự giới hạn / mặc định của lệnh này có thể tái định nghiã bằng cách đơn giản là chỉ thay nó bằng kí tự mới mà không cần khai báo gì thêm.

Thí dụ:

  cat myfile | sed '/1,10/s/Dec/December/g'   

là lệnh hiển thị tập tin myfile nhưng trong 10 dòng đầu tiên nếu xuất hiện chữ Dec thì chữ đó sẽ bị thay bằng chữ December

Các tham số [Cờ_hiệu] có thể được dùng kết hợp với nhau, chúng bao gồm:

  • [n] Chỉ thay thế thực thể thứ n của chuỗi tương hợp với dạng thức trong dòng văn bản hiện tại. Mặc định là 1 tức là vị trí đầu tiên mà dạng thức này tương hợp
  • g Thay thế tất cả các thực thể tương hợp với dạng thức tìm thấy được trong dòng văn bản (chữ g viết tắt cho chữ global)
  • i Tìm thực thể tương hợp và không tính đến việc kí tự có hoa hay không
  • p Hiển thị dòng này nếu có sự thay thế xãy ra; tiện dùng khi gọi bằng lệnh sed -n
  • [Tên_Tập_Tin] Viết lại vào tập tin tên [Tên_Tập_Tin] các dòng xử lý đã được thay thế

Thí dụ:

sed '/[gm]o/s/\bCA/FL/' mydat 

sẽ tìm các hàng trong mydat nào chứa chữ go hay chữ mo (tức là các hàng 1,3,4,5) và nếu trong các hàng đó có chữ nào bắt đầu là CA thì thay thành FL

cat mydat | sed 's/lemon/apple/ig'  

sẽ chuyển nội dung của mydat vào lệnh sed và từ đây, dòng nào có các chữ lemon thì tất cả các chữ lemon này (cho dù là viết hoa hay không) đều bị thay thành chữ apple

sed 's~CA~NY~2' mydat  

Tất các dòng nào trong mydat có chứa sự xuất hiện của chuỗi kí tự CA lần thứ hai sẽ được xử lí bằng cách thay chuỗi xuất hiện CA lần thứ hai này thành chuỗi NY. (Như vậy, chỉ có dòng

Joesmith    CA     Appricot, lemon CA  

được chuyển thành

Joesmith    CA     Appricot, lemon NY

Còn các dòng khác giữ nguyên

sed '/[Ss]mith/s/$/**In Fast Eating Contest**/' mydat

Tất cả các dòng chứa chữ Smith hay smith trong mydat thi hành lệnh s: thay dấu đầu dòng (newline) bởi dòng chữ **In Fast Eating Contest**

Ghi chú về lệnh y

Lệnh y là lệnh "chuyển dịch" các kí tự theo ánh xạ 1-1 từ bảng kí tự nguồn sang bảng kí tự ảnh có cú pháp dạng

y/[Bảng_kí_tự_nguồn]/[Bảng_kí_tự_ảnh]

Tương tự như lệnh s, kí tự giới hạn / có thể hoàn toàn thay thế bằng kí tự khác. Tuy nhiên, lệnh này không hỗ trợ các cờ hiệu

Thí dụ: Lệnh sau đây sẽ chuyển các chữ số từ 0 đến 9 (chỉ tìm thấytrong cột cuối cùng) của tập tin mydat thành các chữ từ A tới J một cách tương ứng (nghiã là 0 → A, 1 → B, 2 → C,..., 9 → J) lên tất cả các dòng nào có chữ CA

sed '/CA/y~0123456789~ABCDEFGHIJ~' mydat

Nhóm lệnh thông tin dòng xử lý

Lệnh Chức năng Thí dụ (RE) Giải thích
= Hiển thị số thứ tự của dòng xử lí  sed '/Smith/=' mydat Hiển thị trước khi nội dung dòng
p Hiển thị nội dung dòng  sed -n '/Smith/gp' mydat Thường dùng kết hợp với sed -n

Nhóm lệnh xử lý I/O

Lệnh Chức năng Thí dụ (RE) Giải thích
e[lệnh] Thực thi một lệnh hệ thống.
Nếu lệnh không có mặt
thì sed lấy nội dung xử lí
làm lệnh để thi hành
 sed '/\blist\b/els' myfile Hiển thị nội dung myfile
và nếu tìm thấy từ list
trong dòng xử lí thì sẽ
thực thi lệnh ls rồi tiếp tục
n Chỉ hiển thị dòng hiện tại
và nhảy xử lí dòng kế tiếp,
dòng điều khiển
cũng chuyển tới lệnh sed kế tiếp
 (xem thí dụ phần kế)
Dùng trong cách viết
lệnh sed lồng nhau
r [Tập_tin] Đọc nội dung của [Tập_tin]
và hiển thị nối tiếp vào trong ngỏ ra,
sau dòng xử lí
 sed '/^List:/r mylist' myform Nếu myform có dòng chữ List:
thì ngay sau dòng này
sed sẽ hiển thị nội dung tập tin mylist
w [Tập_tin] Chép nối nội dung của
dòng thoả mãn vào [Tập_tin]
 sed '/CA/w ca.dat' mydat Chép nối vào tập tin ca.dat
các dòng tìm thấy trong mydat có từ CA
q [Exit_code] Chấm dứt lệnh ngay khi [Vùng_Địa_chỉ]
được tìm thấy
 sed '/lemon/q 1' mydat Hiển thị cho đến khi
dòng xử lí có chữ lemon xuất hiện
trong mydat thì ngưng sau đó
và trả về giá trị 1
Q [Exit_code]
ABCDERGBHJKLMNOPQ
Tương tự lệnh q
nhưng không hiển thị dòng thoả mãn [Vùng_Địa_chỉ]
 sed '/lemon/Q 1' mydat

Nhóm lệnh lưu giữ và trả về

Phần lệnh này đặc biệt thường dùng trong việc sử dụng lệnh sed lồng nhau (xem phần kế sau) hay trong các lệnh sed n'i tiếp nhau thông qua tham số -e. Bằng cách cung ứng một bộ đệm tạm được đặt tên là vùng dạng thức (pattern space)

Lệnh Chức năng
h Chép phần văn bản thoả mãn [Vùng_Địa_chỉ] vào bộ đệm tạm
H Chép nối dấu đầu dòng và tiếp theo là phần văn bản thoả mãn [Vùng_Địa_chỉ] vào bộ dệm tạm
g Chuyển nội dung của vùng dạng thức trở vào dòng xử lý, xóa nội dung của [Dạng _thức].
G Giống như g nhưng nội dung vùng nhớ đệm đưọc chép nối thành dòng mới thay vì xoá nội dung của [Dạng _thức]
x Đổi nội dung cho nhau giữa bộ dệm và nội dung của [Dạng _thức]

Thí dụ:

sed -e '/Ap/H' -e '$g' mydat

Thí dụ trên sẽ hiển thị toàn bộ mydat. Trong khi đó các dòng có chứa chữ Ap sẽ được lưu lại (nối nhau) trong bộ đệm và sau đó lệnh $g sẽ hiển thị lại nội dung của bộ đệm này ở dòng cuối cùng.

Sử dụng các lệnh sed lồng nhau

Trong nhiều trường hợp, người lập trình muốn xử lí một số dòng văn bản liên quan nhau thành khối (như trường hợp đọc các xml file chẳng hạn) thì sed hỗ trợ dạng phân nhánh như cú pháp sau:

sed '[Vùng_Địa_chỉ]{[KHỐI_LỆNH;]} [TÊN_TẬP_TIN]

Lưu ý: Trong [KHỐI_LỆNH;] thì mỗi lệnh của sed phải kết thúc bằng dấu chấm-phẩy (;)

Thí dụ1: Hoàn toàn tương tự như thí dụ trong A16.6, nhưng ở đây các dòng có chứa chữ Ap sẽ không được hiển thị và được giữ trong bộ đệm rồi sau đó mới hiển thị ra. như vậy tương đương với việc lấy các dòng đó ra và chuyển chúng xuống hiển thị cuối cùng

sed -e '/Ap/{H,d}' -e '$g' mydat

Thí dụ2: Thí dụ sau đây sẽ chuyển định dạng cho tập tin :

#content of mytext
This apple is a kind of American fruit
This mango is a kind of Asian fruit
This kiwi is a kind of African fruit
sed '/ of /{ h; s/.* of \(.* fruit\)/\1:/; p; x }' mytext 
#the output should be
American fruit:
This apple is a kind of American fruit
Asian fruit:
This mango is a kind of Asian fruit
African fruit:
This kiwi is a kind of African fruit

Trong thí dụ trên, lệnh h lưu giữ lại dòng xử lí, trong khi lệnh s hiển thị các chữ dạng American fruit:, sian fruit:,African fruit: và sau cùng lệnh x cho xuất (hoán đổi) nội dung của bộ đệm ra


Bài kì tới: Lệnh BASH, Truy sửa lỗi , đa luồng, lspci, awk, makefile, rpm

Chú thích

1:  Nghiã nguyên thuỷ của chữ Daemon là: là một linh hồn dợi sẵn mà có thể ảnh hưởng tới đặc điểm và cá tính của một người nào đó. Từ "daemon được dùng như thuật ngữ computer đầu tiên bởi một thành viên người Anh lập trình trên máy CTSS ở MIT tên là MickBailey trong thập niên 1960.

2:  Các cấp độ khởi động cuả Linux bao gồm

  • 0 dừng máy
  • 1 một người dùng
  • 2-4 người dùng định nghiã
  • 5 dùng chế độ đồ họa X11
  • 6 Tái khởi động

Chế độ mặc định xác định trong /etc/inittab

id:3:initdefault: 

Để thay đổi cấp khởi dộng mặc định dùng /sbin/telinit

3:  Thực chất khi khởi động máy một mệnh lệnh tương tự với đoạn mã sau đây đã được thi hành: (trường hợp này máy đang khởi động ở cấp 2)

for f in /etc/rc2./d/S*
{
   if [ -s ${f} ]; then
      /sbin/sh ${f} start
   fi  
}

4:  Các thư mục khởi động này thường nằm trong /etc hay trong /etc/init.d

5:  Các hỗ trợ này chỉ có trong phiên bản của GNU (dùng trong Linux)


Trở về mục lục

Đọc bài kế

Liên kết đến đây