⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1894.html

📁 著名的linux英雄站点的文档打包
💻 HTML
📖 第 1 页 / 共 5 页
字号:
從 process 的觀念來看,是 parent process 產生一個 child process 去執行, 
當 child 結束後,會返回 parent ,但 parent 的環境是不會因 child 的改變而改變的。 
所謂的環境元數很多,凡舉 effective id, variable, workding dir 等等... 
其中的 workding dir ($PWD) 正是樓主的疑問所在: 
當用 subshell 來跑 script 的話,sub shell 的 $PWD 會因為 cd 而變更, 
但當返回 primary shell 時,$PWD 是不會變更的。 


能夠了解問題的原因及其原理是很好的,但是?如何解決問題恐怕是我們更感興趣的﹗是吧?^_^ 
那好,接下來,再讓我們了解一下 source 命令好了。 
當你有了 fork 的概念之後,要理解 source 就不難: 
* 所謂 source 就是讓 script 在當前 shell 內執行、而不是產生一個 sub-shell 來執行。 
由於所有執行結果均於當前 shell 內完成,若 script 的環境有所改變,當然也會改變當前環境了﹗ 
因此,只要我們要將原本單獨輸入的 script 命令行變成 source 命令的參數,就可輕易解決前例提到的問題了。 
比方說,原本我們是如此執行 script 的: 
代码:
./my.script

現在改成這樣即可: 
代码:
source ./my.script 
或: 
. ./my.script


說到這裡,我想,各位有興趣看看 /etc 底下的眾多設定文件, 
應該不難理解它們被定議後,如何讓其他 script 讀取並繼承了吧? 
若然,日後你有機會寫自己的 script ,應也不難專門指定一個設定文件以供不同的 script 一起"共用"了... ^_^ 

okay,到這裡,若你搞得懂 fork 與 source 的不同,那接下來再接受一個挑戰: 
---- 那 exec 又與 source/fork 有何不同呢? 
哦... 要了解 exec 或許較為複雜,尤其扯上 File Descriptor 的話... 
不過,簡單來說: 
* exec 也是讓 script 在同一個行程上執行,但是原有行程則被結束了。 
也就是簡而言之:原有行程會否終止,就是 exec 與 source/fork 的最大差異了。 

嗯,光是從理論去理解,或許沒那麼好消化,不如動手"實作+思考"來的印像深刻哦。 
下面讓我們寫兩個簡單的 script ,分別命令為 1.sh 及 2.sh : 

1.sh 
代码:

#!/bin/bash 
A=B 
echo "PID for 1.sh before exec/source/fork:$$" 
export A 
echo "1.sh: \$A is $A" 
case $1 in 
        exec) 
                echo "using exec..." 
                exec ./2.sh ;; 
        source) 
                echo "using source..." 
                . ./2.sh ;; 
        *) 
                echo "using fork by default..." 
                ./2.sh ;; 
esac 
echo "PID for 1.sh after exec/source/fork:$$" 
echo "1.sh: \$A is $A" 


2.sh 
代码:

#!/bin/bash 
echo "PID for 2.sh: $$" 
echo "2.sh get \$A=$A from 1.sh" 
A=C 
export A 
echo "2.sh: \$A is $A" 


然後,分別跑如下參數來觀察結果: 
代码:

$ ./1.sh fork 
$ ./1.sh source 
$ ./1.sh exec 


或是,你也可以參考 CU 上的另一貼子: 
<a href="javascript:if(confirm('http://www.chinaunix.net/forum/viewtopic.php?t=191051  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://www.chinaunix.net/forum/viewtopic.php?t=191051'" tppabs="http://www.chinaunix.net/forum/viewtopic.php?t=191051" target="_blank">http://www.chinaunix.net/forum/viewtopic.php?t=191051</a> 

好了,別忘了仔細比較輸出結果的不同及背後的原因哦... 
若有疑問,歡迎提出來一起討論討論~~~ 

happy scripting! ^_^

7) ( ) 與 { } 差在哪? 

嗯,這次輕鬆一下,不講太多... ^_^ 

先說一下,為何要用 ( ) 或 { } 好了。 
許多時候,我們在 shell 操作上,需要在一定條件下一次執行多個命令, 
也就是說,要麼不執行,要麼就全執行,而不是每次依序的判斷是否要執行下一個命令。 
或是,需要從一些命令執行優先次順中得到豁免,如算術的 2*(3+4) 那樣... 
這時候,我們就可引入"命令群組"(command group)的概念:將多個命令集中處理。 

在 shell command line 中,一般人或許不太計較 ( ) 與 { } 這兩對符號的差異, 
雖然兩者都可將多個命令作群組化處理,但若從技術細節上,卻是很不一樣的: 
( ) 將 command group 置於 sub-shell 去執行,也稱 nested sub-shell。 
{ } 則是在同一個 shell 內完成,也稱為 non-named command group。 
若,你對上一章的 fork 與 source 的概念還記得了的話,那就不難理解兩者的差異了。 
要是在 command group 中扯上變量及其他環境的修改,我們可以根據不同的需求來使用 ( ) 或 { } 。 
通常而言,若所作的修改是臨時的,且不想影響原有或以後的設定,那我們就 nested sub-shell , 
反之,則用 non-named command group 。 

是的,光從 command line 來看,( ) 與 { } 的差別就講完了,夠輕鬆吧~~~ ^_^ 
然而,若這兩個 meta 用在其他 command meta 或領域中(如 Regular Expression),還是有很多差別的。 
只是,我不打算再去說明了,留給讀者自己慢慢發掘好了... 
我這裡只想補充一個概念,就是 function 。 
所謂的 function ,就是用一個名字去命名一個 command group ,然後再調用這個名字去執行 command group 。 
從 non-named command group 來推斷,大概你也可以猜到我要說的是 { } 了吧?(yes! 你真聰明﹗ ^_^ ) 

在 bash 中,function 的定義方式有兩種: 
方式一: 
代码:
function function_name { 
    command1 
    command2 
    command3 
    .... 
}

方式二: 
代码:
fuction_name () { 
    command1 
    command2 
    command3 
    .... 
}

用哪一種方式無所謂,只是若碰到所定意的名稱與現有的命令或別名(Alias)衝突的話,方式二或許會失敗。 
但方式二起碼可以少打 function 這一串英文字母,對懶人來說(如我),又何樂不為呢?... ^_^ 

function 在某一程度來說,也可稱為"函式",但請不要與傳統編程所使用的函式(library)搞混了,畢竟兩者差異很大。 
惟一相同的是,我們都可以隨時用"已定義的名稱"來調用它們... 
若我們在 shell 操作中,需要不斷的重覆質行某些命令,我們首先想到的,或許是將命令寫成命令稿(shell script)。 
不過,我們也可以寫成 function ,然後在 command line 中打上 function_name 就可當一舨的 script 來使用了。 
只是若你在 shell 中定義的 function ,除了可用 unset function_name 取消外,一旦退出 shell ,function 也跟著取消。 
然而,在 script 中使用 function 卻有許多好處,除了可以提高整體 script 的執行效能外(因為已被載入), 
還可以節省許多重覆的代碼... 

簡單而言,若你會將多個命令寫成 script 以供調用的話,那,你可以將 function 看成是 script 中的 script ... ^_^ 
而且,透過上一章介紹的 source 命令,我們可以自行定義許許多多好用的 function ,再集中寫在特定文件中, 
然後,在其他的 script 中用 source 將它們載入並反覆執行。 
若你是 RedHat Linux 的使用者,或許,已經猜得出 /etc/rc.d/init.d/functions 這個文件是作啥用的了~~~ ^_^ 

okay,說要輕鬆點的嘛,那這次就暫時寫到這吧。祝大家學習愉快﹗ ^_^

8) $(( )) 與 $( ) 還有${ } 差在哪? 

我們上一章介紹了 ( ) 與 { } 的不同,這次讓我們擴展一下,看看更多的變化:$( ) 與 ${ } 又是啥玩意兒呢? 

在 bash shell 中,$( ) 與 ` ` (反引號) 都是用來做命令替換用(command substitution)的。 
所謂的命令替換與我們第五章學過的變量替換差不多,都是用來重組命令行: 
* 完成引號裡的命令行,然後將其結果替換出來,再重組命令行。 
例如: 
代码:
$ echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)

如此便可方便得到上一星期天的日期了... ^_^ 

在操作上,用 $( ) 或 ` ` 都無所謂,只是我"個人"比較喜歡用 $( ) ,理由是: 

1, ` ` 很容易與 ' ' ( 單引號)搞混亂,尤其對初學者來說。 
有時在一些奇怪的字形顯示中,兩種符號是一模一樣的(直豎兩點)。 
當然了,有經驗的朋友還是一眼就能分變兩者。只是,若能更好的避免混亂,又何樂不為呢? ^_^ 

2, 在多層次的復合替換中,` ` 須要額外的跳脫( \` )處理,而 $( ) 則比較直觀。例如: 
這是錯的: 
代码:
command1 `command2 `command3` `

原本的意圖是要在 command2 `command3` 先將 command3 提換出來給 command 2 處理, 
然後再將結果傳給 command1 `command2 ...` 來處理。 
然而,真正的結果在命令行中卻是分成了 `command2 ` 與 `` 兩段。 
正確的輸入應該如下: 
代码:
command1 `command2 \`command3\` `


要不然,換成 $( ) 就沒問題了: 
代码:
command1 $(command2 $(command3))

只要你喜歡,做多少層的替換都沒問題啦~~~ ^_^ 

不過,$( ) 並不是沒有斃端的... 
首先,` ` 基本上可用在全部的 unix shell 中使用,若寫成 shell script ,其移植性比較高。 
而 $( ) 並不見的每一種 shell 都能使用,我只能跟你說,若你用 bash2 的話,肯定沒問題... ^_^ 

接下來,再讓我們看 ${ } 吧... 它其實就是用來作變量替換用的啦。 
一般情況下,$var 與 ${var} 並沒有啥不一樣。 
但是用 ${ } 會比較精確的界定變量名稱的範圍,比方說: 
代码:
$ A=B 
$ echo $AB 

原本是打算先將 $A 的結果替換出來,然後再補一個 B 字母於其後, 
但在命令行上,真正的結果卻是只會提換變量名稱為 AB 的值出來... 
若使用 ${ } 就沒問題了: 
代码:
$ echo ${A}B 
BB


不過,假如你只看到 ${ } 只能用來界定變量名稱的話,那你就實在太小看 bash 了﹗ 
有興趣的話,你可先參考一下 cu 本版的精華文章: 
<a href="javascript:if(confirm('http://www.chinaunix.net/forum/viewtopic.php?t=201843  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://www.chinaunix.net/forum/viewtopic.php?t=201843'" tppabs="http://www.chinaunix.net/forum/viewtopic.php?t=201843" target="_blank">http://www.chinaunix.net/forum/viewtopic.php?t=201843</a> 

為了完整起見,我這裡再用一些例子加以說明 ${ } 的一些特異功能: 
假設我們定義了一個變量為: 
file=/dir1/dir2/dir3/my.file.txt 
我們可以用 ${ } 分別替換獲得不同的值: 
${file#*/}:拿掉第一條 / 及其左邊的字串:dir1/dir2/dir3/my.file.txt 
${file##*/}:拿掉最後一條 / 及其左邊的字串:my.file.txt 
${file#*.}:拿掉第一個 . 及其左邊的字串:file.txt 
${file##*.}:拿掉最後一個 . 及其左邊的字串:txt 
${file%/*}:拿掉最後條 / 及其右邊的字串:/dir1/dir2/dir3 
${file%%/*}:拿掉第一條 / 及其右邊的字串:(空值) 
${file%.*}:拿掉最後一個 . 及其右邊的字串:/dir1/dir2/dir3/my.file 
${file%%.*}:拿掉第一個 . 及其右邊的字串:/dir1/dir2/dir3/my 
記憶的方法為: 
# 是去掉左邊(在鑑盤上 # 在 $ 之左邊) 
% 是去掉右邊(在鑑盤上 % 在 $ 之右邊) 
單一符號是最小匹配﹔兩個符號是最大匹配。

${file:0:5}:提取最左邊的 5 個字節:/dir1 
${file:5:5}:提取第 5 個字節右邊的連續 5 個字節:/dir2 

我們也可以對變量值裡的字串作替換: 
${file/dir/path}:將第一個 dir 提換為 path:/path1/dir2/dir3/my.file.txt 
${file//dir/path}:將全部 dir 提換為 path:/path1/path2/path3/my.file.txt 

利用 ${ } 還可針對不同的變數狀態賦值(沒設定、空值、非空值): 
${file-my.file.txt} :假如 $file 為空值,則使用 my.file.txt 作默認值。(保留沒設定及非空值) 
${file:-my.file.txt} :假如 $file 沒有設定或為空值,則使用 my.file.txt 作默認值。 (保留非空值) 
${file+my.file.txt} :不管 $file 為何值,均使用 my.file.txt 作默認值。 (不保留任何值) 
${file:+my.file.txt} :除非 $file 為空值,否則使用 my.file.txt 作默認值。 (保留空值) 
${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 作默認值,同時將 $file 定義為非空值。 (保留空值及非空值) 
${file:=my.file.txt} :若 $file 沒設定或為空值,則使用 my.file.txt 作默認值,同時將 $file 定義為非空值。 (保留非空值) 
${file?my.file.txt} :若 $file 沒設定,則將 my.file.txt 輸出至 STDERR。 (保留空值及非空值)) 
${file:?my.file.txt} :若 $file 沒設定或為空值,則將 my.file.txt 輸出至 STDERR。 (保留非空值) 

還有哦,${#var} 可計算出變量值的長度: 
${#file} 可得到 27 ,因為 /dir1/dir2/dir3/my.file.txt 剛好是 27 個字節... 

接下來,再為大家介稍一下 bash 的組數(array)處理方法。 
一般而言,A="a b c def" 這樣的變量只是將 $A 替換為一個單一的字串, 
但是改為 A=(a b c def) ,則是將 $A 定義為組數... 
bash 的組數替換方法可參考如下方法: 
${A[@]} 或 ${A[*]} 可得到 a b c def (全部組數) 
${A[0]} 可得到 a (第一個組數),${A[1]} 則為第二個組數... 
${#A[@]} 或 ${#A[*]} 可得到 4 (全部組數數量) 
${#A[0]} 可得到 1 (即第一個組數(a)的長度),${A[3]} 可得到 3 (第一個組數(def)的長度) 
A[3]=xyz 則是將第 4 個組數重新定義為 xyz ... 

諸如此類的.... 
能夠善用 bash 的 $( ) 與 ${ } 可大大提高及簡化 shell 在變量上的處理能力哦~~~ ^_^ 

好了,最後為大家介紹 $(( )) 的用途吧:它是用來作整數運算的。 
在 bash 中,$(( )) 的整數運算符號大致有這些: 
+ - * / :分別為 "加、減、乘、除"。 
% :餘數運算 
&amp; | ^ !:分別為 "AND、OR、XOR、NOT" 運算。 

例: 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -