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 hay in lại nhằm
mục đích mua bán
hay trục lợi mà không có sự đồng ý 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 xin liên lạc về
vo_quang_nhan@yahoo.com
Bài 4:
14 Các biến môi trường
Biến môi trường là biến toàn cục thường đã được định nghiã từ
trước giá trị của nó. Khi viết các văn lệnh bạn nên tránh
dùng các tên biến trùng với tên đã được định nghiã bởi BASH. Để
hiển thị tên và giá trị hiện tại của
một số biến môi trường có thể
dùng lệnh
env .
Số khác có thể không có mặt trong nội dung của $env hay chưa đuợc
định nghiã. Trong trường hợp biến đã được xác định thì có
thể dùng cú pháp:
echo $<TÊN_BIẾN>
để hiển thị nội dung (chẳng hạn như lệnh
echo $PS1
sẽ cho giá trị cài đặt của biến môi trường PS1)
Các biến môi trường này có thể thường trực tồn tại hoặc chỉ tồn
tại trong điều kiện nào đó (như là chỉ có khi chạy một văn lệnh
chẳng hạn). Giá trị của các biến môi trường quan trọng là:
14.1
$BASH
đường dẫn của tập tin trình dịch BASH (thường là
/bin/bash )
14.2
$GROUPS
nhóm người dùng
14.3
$HOME
Thư mục truy cập của người dùng, thưuờng được viết tắt là ~ (xem
tham số mở
rộng trong BASH)
14.4
$HOSTNAME tên của hệ thống (máy chủ)
14.5
$HOSTTYPE
hệ thống phần cứng
14.6
$IFS
Biến ngăn cách-- BASH lưu giá trị mặc định của kí tự ngăn cách
giữa các miền (field) thường dùng trong các vòng lặp.(xem
bài 3)
14.7
$MACHTYPE
Kiểu hệ thống
(cpu-company-system )
Thí dụ:
$echo "$MACHTYPE"
$i686-pc-linux-gnu
14.8
$OLDPWD
tên thư mục hiện hoạt trước đây (tên cuối cùng trước khi thư mục
hiện hoạt bị thay đổi). Khi mới dăng nhập thì biến này không tồn
tại. Nhưng một khi người dùng đang ở thư mục A và chuyển
thư mục hiện hoạt sang bất kì thư mục B nào khác thì
$OLDPWD
sẽ được tạo ra bởi BASH và có giá trị là A. (xem thêm
$PWD
ở 14.11)
14.9
$OSTYPE
tên bản nền (platform)
14.10
$PATH
nội dung bao gồm các đường dẫn để BASH tự động tìm đên và thi
hành một khi có các mệnh lệnh được gọi mà không có cung cấp tên
đầy đủ
14.11
$PWD
tên thư mục hiện hoạt. Khi di chuyển sang thư mục khác (bằng
lệnh
cd
chẳng hạn) thì giá trị cũ sẽ
được gán cho
$OLDPWD ,
còn giá trị của thư mục vừa chuyển tới được cập nhật vào
$PWD
(xem thêm
$OLDPWD
ở 14.8)
14.12
$PPID
ID của tiến trình của chương trình
cha mẹ đang chạy (Trong một
văn lệnh đang chạy thì
$PPID
là số tiến trình
của BASH đang dùng để chạy văn lệnh đó)
14.13
$RANDOM
Biến này sẽ chứa một giá trị ngẫu nhiên khác nhau mỗi lần nó được
truy cập. Số ngẫu nhiên này là số nguyên từ 0 tới 23767 (thực
chất đây là một số giả ngẫu nhiên (pseudo-randomize number) is an integer
in rang 0..32767
Thí dụ:
MyNum1="$RANDOM"
MyNum2="$RANDOM"
echo "the values are $MyNum1 $MyNum2"
14.14
$SECONDS
số thời gian tính bằng giây mà văn lệnh đã chạy
14.15
$UID
ID của người dùng
14.16
$CPU
CPU trên máy
14.17
$LOGNAME:
Tên người dăng nhập
14.18
$USER:
Tên người dùng
14.19
$SHELL:
tên đầy đủ của trình bao gán
cho người dùng
14.20
$PS1 Dòng hiển thị của dấu
nhắc (prompt) sơ cấp. Giá trị của biến này sẽ quy định
cách thức và nội dung hiển thị.
Thí dụ:
SuSE SLES 9 có thể cài mặc định dòng nhắc là
h:w #
Tức là nó sẽ cho ra dòng như là
<Tên_máy_chủ>:<Tên_thư_mục_hiện_hoạt>
#. Bạn có thể cài đặt lại dòng
hiển thị này bằng cách gán giá trị mới cho
IPS .
Thí dụ: để dòng hiển thị báo ngày hiện tại và thư mục
hiện hoạt thì có thể dùng lệnh
IPS="\d-\w #"
\d
ngày tháng
\D{<định_dạng>}
Dòng strftime(3)
sẽ đưa gian hiện tại vào; nếu
<định_dạng>
không có thì sẽ hiện thị
theo cách cài đặt thời gian theo địa phương .
Dấu ngoặc
{ }
phải có mặt để BASH hiểu tham số này (Xem thêm chi tiết
về cách định dạng dòng thời gian xuất ra bởi lệnh
man 3 strftime ).
sau đây là một số giá trị có thể dùng của PS1
\e Kí tự thoát.
\h
Tên máy chủ (hostname) cho đến dấu chấm . đầu tiên.
\H Tên máy chủ.
\l
Tên của thiết bị đầu cuối chạy trình bao
\n Kí tự đầu dòng.
\r
Kí tự xuống hàng.
\s
Tên của văn lệnh (giá trị tên không đầy đủ của $0)
\t
Thời gian, kiểu 24-giờ dạng HH:MM:SS.
\T
Thời gian, kiểu 12-giờ dạng HH:MM:SSt.
\@
Thời gian, kiểu 12-giờ dạng am/pm.
\A
Thời gian, kiểu 24-giờ dạng HH:MM.
\u
Tên tài khoảng của người đang dùng.
\v Số phiên bản của Bash
\V Số phiên bản phát hành của Bash, version + patchlevel (e.g., 2.00.0)
\w
Tên thư mục hiện hoạt.
\W
Tên không đầy đủ của $PWD.
\!
Sử số (history number) của lệnh này.
\#
Lệnh số (command number) của lệnh này.
\nnn Kí tự trong mã ASCII mà giá trị bát phân là nnn.
\\ Dấu nghiên về (backslash)
\[ Kí tự mở đầu của một dãy kí tự không in được
(non-printing character). Có thể dùng để nhúng (embed) dãy
điều khiển đầu cuối vào trong dòng nhắc (prompt string).
\] Kí tự kết thúc của một dãy kí tự không in được
14.21
$PS2
Dòng nhắc thứ cấp. Gíá trị
mặc định là > .
Biến này thường thấy hiển thị trên thiết bị đầu cuối mỗi khi
người dùng gõ xong dòng lệnh nhưng vẩn chưa kết thúc đầy đủ.
Thí dụ nếu người dùng gõ lệnh
myvar=test; echo "myvar (thiếu một dấu ngoặc kép)
thì BASH sẽ hiển thị dòng nhắc thứ cấp. (tức là dấu > )
để kết thúc người dùng có thể gõ thêm dấu
"
hay kết thúc lệnh đó bằng tổ hợp phím <Ctrl>+<c>
14.23 $BASH_VERSION
Số phiên bản đầy đủ của thực thể BASH.
14.24 BASH_VERSINFO
là
mảng các hằng lưu giữ thông tin về phiên bản của thực thể
BASH các giá trị bao gồm:
$BASH_VERSINFO[0]
Chính số của phiên bản (bản phát hành).
$BASH_VERSINFO[1]
Phụ số của phiên bản (bản phát hành).
$BASH_VERSINFO[2]
Cấp che vá.
$BASH_VERSINFO[3]
Phiên bản dựng (build version)
$BASH_VERSINFO[4]
Tình Trạng phát hành (thí dụ
beta1).
$BASH_VERSINFO[5]
Giá tri- của biến MACHTYPE.
14.25 $FUNCNAME
Tên của hàm đang được thi hành bên trong trình bao.
Biến này chỉ tồn tại trong khi một hàm đang được thực thi.
Không thể gán giá trị mới cho nó (sẽ nhận về trạng thái lỗi)
14.26 $LINENO
Số thứ tự của dòng hiện tại trong văn lệnh hay của hàm (của
trình bao) đang được thực thi
14.27
$PROMPT_COMMAND
Nếu được cài thì giá trị của biến này sẽ được hiểu như là một
mệnh lệnh để thi hành trước khi hiển thị dòng nhắc sơ
cấp ($PS1).
14.28 $PS3
giá trị của biến này chỉ dùng trong việc hiển thị của
lệnh select.
Giá trị mặc định là
#?
14.29 $SHLVL
Sẽ tăng 1 đơn vị mỗi lần có một thực thể của BASH được bắt đầu.
Biến này chủ ý được dùng để tính độ sâu như thế nào mà các
trình bao BASH lồng nhau.
14.30
$TMOUT
Nếu được cài giá trị lớn hơn 0 thì,
TMOUT sẽ trở
thành thời gian hết hạn mặc định cho việc đọc (từ console
chẳng hạn).
Lệnh select
sẽ kết thúc nếu nó không nhận đưọc dữ liệu nhập từ thiết bị
đầu cuối sau khoảng thời gian
$TMOUT giây.
Trong các hệ vỏ tương tác, gía trị này là số giây để đợi dữ
liệu nhập sau một lệnh dòng nhắc. BASH sẽ ngừng sau số giây
$TMUOT nếu mà
dữ liệu nhập chưa đến.
15 Tham số đặc biệt
quan trọng (phân biệt với lệnh dạng
kí tự)
Các tham số đặc biệt này chỉ được dùng để đọc giá trị và
BASH không cho phép gán giá trị lên chúng.
15.1
0, 1, 2 ,...
các tham số của văn lệnh (hay của hàm) từ vị trí 0, 1, 2...nếu
nó được gọi. BASH cung cấp tối da 10 giá tri (từ
$0 tới $9).
Trong trường hợp gọi một văn lệnh thì $0
là tên của văn lệnh, $1 là giá trị
của tham số đầu tiên,
$2 là giá trị của tham số thứ nhì,....
Ngoài ra, ngoại trừ giá trị
$0 không đổi, các tên
$<n> (n
> 0) sẽ nhận giá trị chứa trong
$<n+1> sau mỗi lần thi hành lệnh
shift. Do đó, nếu gọi giá trị
$<max>, trong đó max là tên biến
lớn nhất chứa giá trị khác null, sau mỗi lệnh shift sẽ chưá giá
trị null (vì giá trị khác null của nó đã chuyển cho
$<max-1>
Thí dụ:
#the affect of 'shift' on $1, $2, $3,...
#!/bin/bash
# file name: ShiftTest
echo "the values of parameters are: $0, $1, $2, $3, $4, and $5"
shift
echo "after calling shift, their values become: $0, $1, $2, $3, and
$4"
After saving under the name ShiftTest, issue commands:
#chmod 755 ./ShiftTest
#./ShiftTest one two three four five
The Scipt will display as
#the values of paramaters are: one, two, three, four, and five
#after calling shift their values become: two, three, four, and
five
15.2
#
biến này chứa tổng số tham số có giá
trị khác null khi văn lệnh được gọi.
15.3
?
Biến chứa mã thoát của mệnh lệnh
cuối cùng trong văn lệnh trả về (giá trị này thường là 0 nếu mệnh
lệnh thi hành thành công)
Thí dụ:
echo "bash location :$BASH"
echo "number of argument when calling this script :$#"
if [ ! $# -eq 2 ]; then
# if there are not 2 arguments then
echo "too many parameters given"
#display error
exit 1
#Exit code = 1
else
echo "now we copy file $1 to $2"
cp -f $1 $2 1>/dev/null 2>/dev/null #copy file
but suppress output messages
if [ $? = 0 ]; then
echo
"copied."
else
echo "error
while copying with the error code $?"
fi
fi
15.4
* Cho
danh sách các tham số vị trí, bắt đầu từ vị trí 1. Như vậy
$* sẽ là danh
sác các tham số được ngăn cách nhau bởi dấu ngăn cách
$IFS.
Nếu để cài đặt mặc định thì
$*
tương đương với string
"$1
$2 $3 ...$n" (với
$n
là tham số cuối cùng
khác null)
15.5
@
Nội
dung của $@ sẽ là danh sách
các tham số vị trí, bắt đầu từ vị trí 1. Tuy nhiên, danh sách đó có dạng
"$1" "$2"
... ."$n".
Khi không có tham số $@ có giá trị
null.
15.6
$ Cung
cấp ID của tiến trình của trình bao. Trong một
trình bao con
( ) , $$
là ID của tiến trình của trình bao gọi không phải của trình
bao con 15.7
! Nội
dung là tiến trình ID của lệnh sau cùng được thực thi trong nền (một cách không
đồng bộ).
16
Quy ước về sử dụng dấu ngã
~
(tilde)
Trong BASH dấu ~ mang ý nghiã đặc biệt. tùy theo các kí tự nối theo sau nó.
~ Giá trị của $HOME.
Thí dụ: ~/mydir
tương đương với thư mục $HOME/mydir
~ <Tên_tài_khoản>/ Trả về tên thư mục nhà (home directory) của <Tên_tài_khoản>
~+
Tương đương
với
gía trị
$PWD
~-
Tương đương
với
gía trị
$OLDPWD
16 Hàm
Giống như C/C++Linux, BASH xem thủ tục cũng là mộtdạng hàm không có
tham số. Cú pháp của một hàm thường là một trong các dạng
- function <TÊN_HÀM> {
<KHỐI_LỆNH>
}
<TÊN_HÀM> () {
<KHỐI_LỆNH>
}
<TÊN_HÀM> ()
{
<KHỐI_LỆNH>
}
16.1 Đặc điểm chung của hàm trong BASH
- Khi thưc thi một văn lệnh, có thể có trường hợp các mệnh
lệnh, các lệnh nội tại, các tên thay thế (chẳng
hạn như các tên làm ra từ lệnh
alias ) và các hàm có
cùng tên, thì BASH sẽ ưu tiên tìm tới tên thay thế trước, sau đó
là tên hàm, và sau cùng mới tìm kiếm trong các mệnh lệnh theo
thứ tự này. Do đó, nên tránh đặt tên các hàm trùng với
các tên thay thế. Ngoài ra, khi gọi các mệnh lệnh có cùng tên
với hàm trong văn lệnh thì tốt nhất là dùng tên đầy đủ của mệnh
lệnh đó
- Hàm phải được định nghiã trước khi nó được sử dụng
- Các biến thông thường của một hàm được chia sẽ chung trong
một văn lệnh.
Tuy nhiên, một biến địa phương có thể được tạo ra bởi từ khoá
local
( Thí dụ như local local_var=10)
- Nếu sử dụng câu lệnh
return
trong một hàm thì nó sẽ lập tức trả dòng điều khiển về cho dòng
điều khiển chính của văn lệnh và giá trị trả về (return) chính
là giá trị thoát (exit status) mệnh lệnh cuối cùng mà hàm đó
thực thi. Để chỉ thị một giá trị xác định khi trả về thì
người ta dùng cú pháp
return <n>
(chẳng hạn như return 2 hay
là return $number)
- Một hàm có thể được xuất cho các trình bao con bằng cách
dùng câu lệnh với cú pháp:
export -f
<TÊN_HÀM>
-
Các hàm được chứa trong một tập tin khác cùng có thể tải lên văn
lệnh hiện hoạt bằng mệnh lệnh:
.
<TÊN_TẬP_TIN_HÀM>
hay là
source
<TÊN_HÀM>
( Thí dụ: để sử dụng các hàm có định nghiã
trong một tập tin là
myFunc , thì người ta có thể
tải nó trước bằng các thêm lệnh . myFunc
(hay lệnh
source myFunc )
vào trong văn lệnh hiện tại) -
BASH hỗ
trợ khả năng đệ quy của các hàm
- Bên trong một hàm có thể gọi hàm khác. (xem
Thí dụ)
- Để xóa khỏi bộ nhớ hàm đã được tải từ trước, dùng lệnh có cú
pháp:
unset -f <TÊN_HÀM>
- Để hiển thị lại danh mục các hàm đã định
nghiã từ trước dùng
declare -f
(xem
lại bài 2)
Thí dụ1:
#!/bin/bash
#script file name :hello
hello () #define this function before calling it
{
echo "hello world"
return 0 #optional you may
add/remove this line
}
echo "call function hello()"
hello
Thí dụ2: Xuất các
hàm sang nơi khác
Nội dung của tập tin file1:
#!bin/bash
#file name file1
#calling the function myfunc in the parent scripts (file2)
echo "calling from the child scripts"
myfunc
exit 0
Nội dung của tập tin file2:
#!/bin/bash
#file name file2
#Exporting function myfunc to all of its childs
myfunc ()
{
echo "myfunc running"
}
#now call the child script to see what is done
# remember: chmod 755 ./file1
./file1
16.2 Truyền tham số và đọc gía trị
trả về từ một hàm
16.2.1 Truyền tham số:
- Sử dụng các đối số theo cú pháp:
<TÊN_HÀM>
<TÊN_BIẾN1>
<TÊN_BIẾN2>
<TÊN_BIẾN3>
...
Với phương pháp này thì bên trong hàm thì nội dung
$<TÊN_BIẾN1>
sẽ được gán thành
$1 ,
$<TÊN_BIẾN2>
sẽ được gán thành
$2 ,
và
$<TÊN_BIẾN3>
sẽ được gán thành
$3
,....(xem thí dụ)
- Sử dụng việc truyền tham số như là các biến thông thường.
Tất cả các biến được định nghiã trong một văn lệnh sẽ được xem
như là biến toàn cục của riêng văn lệnh đó (nếu chúng không
được
khai
báo địa phương) và do đó chúng có thể được truy cập trực
tiếp bên trong một hàm của văn lệnh này
16.2.2 đọc giá trị
trả về:
- Tiếp nhận giá trị nguyên trả về bằng lệnh return bên trong
hàm (thí dụ2).
Trường hợp này giá trị trả về chứa trong tham số đặc biệt
#?
- Tiếp nhận giá trị của các tham số thông qua các biến trong
văn lệnh. Các biến trong một tập tin là biến toàn cục đối với
tập tin đó, nên chúng có thể được thay đổi giá trị này bên
trong hàm và được đọc lại từ bên ngoài hàm
- Tiếp nhận các giá trị từ ngỏ ra của hàm. Trong trường hợp
này hàm có thể dùng lệnh
echo
để xuất giá trị. (thí
dụ3) Việc gọi hàm và giá trị tiếp nhận giá trị trả
ra thông qua cú pháp :
$(<TÊN_HÀM>
<TÊN_BIẾN1>
<TÊN_BIẾN2>
<TÊN_BIẾN3>
...)
16.2.3 Thí dụ:
Các thí dụ mô phỏng từ mã có trong các nguồn mở nêu
ở
tài
liệu tham khảo
Thí dụ1: Truyền tham số bằng các biến thông thường
#!/bin/bash
myfunc ()
{
echo " data passing before: data=$dat, number=$num"
data="new value"
num=0
}
#now declaring variables
dat="orig value"
num=12
Thí dụ2: Nhận giá trị trả ra từ
hàm.
Thí dụ
tính tổng hai số nguyên từ hàm sum
#!/bin/bash
function sum {
if [ ! "$#" = "2" ]; then
echo "ERROR: the number of
parameters must be 2"
return
else
local total
let "total = $1 + $2"
echo "is $total"
if
}
value=$(sum 2 3)
echo "total of 2 and 3 $value"
16.3
Gọi các hàm đã được định nghĩa trong một
tập tin khác :
Như có nhắc trong phần đặc điểm, để việc chia sẽ mã nguồn được tiện
lợi, BASH hỗ trợ một lệnh để tải một tập tin khác có chưá các thông tin hay các
hàm và dùng nó để chia sẽ. Tập tin được tải có thể có mã nguồn trực tiếp
sử dụng các biến hay tham số đã được định nghiã trong tập tin khai báo. Ngược
lại, tập tin khai báo có thể gọi tất cả các hàm hỗ trợ sẵn có trong tập tin được
tải. Cú pháp dể khai báo tải một tập tin
.
<TÊN_TẬP_TIN_HÀM>
hay là source
<TÊN_TẬP_TIN_HÀM>
Thí dụ: Gọi hàm từ các tập tin ở
nơi khác.
Nội dung của tập tin
myFunc chứa định nghiã của các hàm, nó cần được tải và gọi bởi
một văn lệnh khác
#!/bin/bash
#file name myFunc
func1 ()
{
if [ $# -eq 1 ];then
echo "the 1st parameter passed
into func1 is $1"
elif [ "$1" = "" ]; then
echo "no parameter passed into
func1"
else
echo "more than one parameters
passed"
if
}
internal_Usage_Func ()
{
echo "error : $*" 2>&1
echo "program $0 is terminated"
exit 1
}
func2
()
{
#recursive and internal function calling demo
if [ ! "$#" = "1" ]; then
internal_Usage_Func "func2()
called from $0 require single argument"
#in this case $0 will be the
invoking script (mother)
#so it not be Expect as myFunc
else
local
number=$1
# Variable
"number" must be declared as local,
#
otherwise this doesn't work.
if [
$number -eq 0 ];
then
factorial=1 # Factorial of 0 = 1.
else
let "decrnum = number - 1"
func2 $decrnum # Recursive function call.
let "factorial = $number * $?"
fi
return
$factorial
fi
}
Nội dung của tập tin chính bao gồm việc khai báo tải và gọi
các hàm từ tệp myFunc
#!/bin/bash
#file name mother
. myFunc #declaring function will be loaded
# equivalent declaring: source myFunc
#now calling functions of file myFunc
echo "func1 with 1 argument"
func1 hi
echo "func1 with 2 arguments"
func1 hello world
echo "---------"
#testing func2 recursive function
N=3
func2 $N
echo "factorial of 3 is $?. This number is retrieved
from func2"
echo "now test the internal function call"
func2 #no argument to trigger
The output
when invoking mother should look like:
#func1 with 1
argument
#the 1st parameter
passed into func1 is hi
#func1 with 2 arguments
#more than one parameters passed
#--------
#factorial of 3 is 6
#error : func2() called from mother require single argument
#program mother is terminated"
A14 Sử dụng trình dịch GNU C/C++
A14.1 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ố
|
Tên_tập_tin] :
Cho tất cả cá chương trình ngôn ngữ C
-
g++
[Tham_số
|
Tên_tập_tin] :
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, and 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++.
A14.2 N hững tham số thông dụng trong trình dịch
GNU:
<ngôn_ngữ> ]
: 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
To run the myhello command
#./myhello
the message should look like
#hello
A14.3 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.
A14.4 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)
A14.5 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 comile use this command"
gcc -static mountcd.c -o mountcd
A14.6 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
A14.7 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++
A15 Tác trình và cách tạo ra
A15.1 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ánbh 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
A15.2
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();
<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
A15.3 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.
A15.4 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.
A15.5 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ì:
-
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.
-
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
)
-
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
-
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
-
Tái khởi động máy hay gọi
telinit
để hoạt hoá các tác trình
A15.6 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
A16 Sử dụng lệnh sed
A16.1 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ộ.)
A16.2 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.
A16.3 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.
A16.4
[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
- <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ó.
-
<n>
: dòng văn bản thứ n được chỉ định
- $ : dòng cuối cùng nhập từ ngỏ vào
- +<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)
- ~<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 ( , ):.
- 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
-
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.
- /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ử kí 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)
- 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)
- /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
A16.5 Biểu thức chính quy
trong sed:
A16.5.1 Hỗ trợ thông thường
A16.5.1.1 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 ra%'t
tiện lợi khi soạn thảo mà các dòng văn bản có nhiều đọan 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
A16.5.1.2
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
A16.5.2 Bảng 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 |
|
|
|
A16.6 Các nhóm lệnh thông dụng của
sed
A16.6.1 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 |
cat mydat| 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 |
ls | 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 |
|
|
A16.6.1.1 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
- w <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 CA 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**
A16.6.1.2 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
A16.6.2 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 |
A16.6.3 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 tới 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] |
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 |
|
A16.6.4 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.
A16.7 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
(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
- Để 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ỗ tợ này chỉ có trong phien
bản của GNU (dùng trong Linux)
Bài kì tới:
Lệnh BASH,
Truy sửa lỗi , đa luồng, lspci, awk, makefile,
rpm
© http://vietsciences.free.fr ,
http://vietsciences.org
và
http://vietsciences2.free.fr
Làng Đậu |