首页 | 论坛 | Linux | 博客 | 下载 | 人才 | 培训 | WIKI | 手册 | 图书 | 搜索  
ChinaUnix.net » Shell » shell 十三問?

2003-12-12 17:35 newince
shell 十三問?

生动、易懂!

2003-12-13 09:54 nibo
shell 十三問?

精..继续撒!!还有好多!

2003-12-13 22:51 admirer
shell 十三問?

[b]Redirect Operators and File Descriptors[/b]
[quote][b]<&n[/b] redirect standard input from file descriptor n
[b]>&n[/b] redirect standard output to file descriptor n
[b]n<file[/b] redirect file descriptor n from file
[b]n>file[/b] redirect file descriptor n to file
[b]n>>file[/b] redirect file descriptor n to file. Create file if non-existent, else overwrite.
[b]n>| file[/b] redirect file descriptor n to file. Create file even if noclobber is enabled.
[b]n<&m[/b] redirect file descriptor n input from file descriptor m
[b]n>&m[/b] redirect file descriptor n output to file descriptor m
[b]n<>file[/b] open file for reading and writing as file descriptor n
[b]n<<word[/b] redirect to file descriptor n until word is read
[b]n<<-word[/b] redirect to file descriptor n until word is read; ignore leading tabs
[b]n<&-[/b] close file descriptor n for standard input
[b]n>&-[/b] close file descriptor n for standard output
[b]print &u[/b][i]n args[/i] redirect arguments to file descriptor n. If n is greater than 2, it must first be opened with exec. If n is not specified, the default file descriptor argument is 1 (standard output).
[b]read &u[/b][i]n args[/i] read input line from file descriptor n. If n is greater than 2, it must first be opened with exec. If n is not specified, the default file descriptor argument is 0 (standard input).[/quote]

2003-12-14 05:37 七爷
shell 十三問?

恩,基础是很重要的,希望大家互相帮助。:)

2003-12-16 01:11 網中人
shell 十三問?

3) 別人 echo、你也 echo ,是問 echo 知多少?

承接上一章所介紹的  command line ,這裡我們用 echo 這個命令加以進一步說明。
溫習---標準的 command line 包含三個部件:
* command_name option argument

echo 是一個非常簡單、直接的 Linux 命令:
* 將 argument 送出至標準輸出(STDOUT),通常就是在監視器(monitor)上輸出。
(註:stdout 我們日後有機會再解說,或可先參考如下討論:
[url]http://www.chinaunix.net/forum/viewtopic.php?t=191375[/url] )

為了更好理解,不如先讓我們先跑一下 echo 命令好了:
[code]$ echo

$[/code]
你會發現只有一個空白行,然後又回到 shell prompt 上了。
這是因為 echo 在預設上,在顯示完 argument 之後,還會送出一個換行符號(new-line charactor)。
但是上面的 command 並沒任何的 argument ,那結果就只剩一個換行符號了...
若你要取消這個換行符號,可利用 echo 的 -n option :
[code]$ echo -n
$[/code]
不妨讓我們回到 command line 的概念上來討論上例的 echo 命令好了:
* command line 只有 command_name(echo) 及 option(-n),並沒有任何 argument 。
要想看看 echo 的 argument ,那還不簡單﹗接下來,你可試試如下的輸入:
[code]$ echo first line
first line
$ echo -n first line
first line $[/code]
於上兩個 echo 命令中,你會發現 argument 的部份顯示在你的熒幕,而換行符號則視 -n option 的有無而別。
很明顯的,第二個 echo 由於換行符號被取消了,接下來的 shell prompt 就接在輸出結果同一行了... ^_^

事實上,echo 除了 -n options 之外,常用選項還有:
        -e :啟用反斜線控制字符的轉換(參考下表)
        -E:關閉反斜線控制字符的轉換(預設如此)
        -n :取消行末之換行符號(與 -e 選項下的 \c 字符同意)

關於 echo 命令所支援的反斜線控制字符如下表:
        \a:ALERT / BELL (從系統喇叭送出鈴聲)
        \b:BACKSPACE ,也就是向左退格鍵
        \c:取消行末之換行符號
        \E:ESCAPE,跳脫鍵
        \f:FORMFEED,換頁字符
        \n:NEWLINE,換行字符
        \r:RETURN,回車鍵
        \t:TAB,表格跳位鍵
        \v:VERTICAL TAB,垂直表格跳位鍵
        \n:ASCII 八進位編碼(以 x 開首為十六進位)
        \\:反斜線本身
        (表格資料來自 O'Reilly 出版社之 Learning the Bash Shell, 2nd Ed.)

或許,我們可以透過實例來了解 echo 的選項及控制字符:

例一:
[code]$ echo -e "a\tb\tc\nd\te\tf"
a       b       c
d       e       f[/code]
上例運用 \t 來區隔 abc 還有 def ,及用 \n 將 def 換至下一行。

例二:
[code]$ echo -e "\141\011\142\011\143\012\144\011\145\011\146"
a       b       c
d       e       f[/code]
與例一的結果一樣,只是使用 ASCII 八進位編碼。

例三:
[code]$ echo -e "\x61\x09\x62\x09\x63\x0a\x64\x09\x65\x09\x66"
a       b       c
d       e       f[/code]
與例二差不多,只是這次換用 ASCII 十六進位編碼。

例四:
[code]$ echo -ne "a\tb\tc\nd\te\bf\a"
a       b       c
d       f $[/code]
因為 e 字母後面是退格鍵(\b),因此輸出結果就沒有 e 了。
在結束時聽到一聲鈴嚮,那是 \a 的傑作﹗
由於同時使用了 -n 選項,因此 shell prompt 緊接在第二行之後。
若你不用 -n 的話,那你在 \a 後再加個 \c ,也是同樣的效果。

事實上,在日後的 shell 操作及 shell script 設計上,echo 命令是最常被使用的命令之一。
比方說,用 echo 來檢查變量值:
[code]$ A=B
$ echo $A
B
$ echo $?
0[/code]
(註:關於變量概念,我們留到下兩章才跟大家說明。)

好了,更多的關於 command line 的格式,以及 echo 命令的選項,
就請您自行多加練習、運用了...

[[i] 本帖最后由 網中人 于 2008-10-30 02:08 编辑 [/i]]

2003-12-16 16:03 黑骏马
shell 十三問?

网中人兄:
   能不能把:
其中的 IFS 是 shell 預設使用的欄位分隔符號,可以由一個及多個如下按鍵組成:
* 空白鍵(White Space)
* 表格鍵(Tab)
* 回車鍵(Enter)
IFS讲详细一点?
谢谢!

2003-12-16 16:23 美丽心情
shell 十三問?

唉,netman大哥总结的真好。
感觉到自己是多么的渺小啊 :em06:

2003-12-17 08:11 網中人
shell 十三問?

[quote][i]原帖由 "黑骏马" 发表:[/i]
网中人兄:
   能不能把:
其中的 IFS 是 shell 預設使用的欄位分隔符號,可以由一個及多個如下按鍵組成:
* 空白鍵(White Space)
* 表格鍵(Tab)
* 回車鍵(Enter)
IFS讲详细一点?
谢谢![/quote]
呵、、、 這是下一章的重點哦﹗  ^_^

2003-12-17 13:56 fx301080
shell 十三問?

看了這後真是受益很多

2003-12-18 11:55 黑骏马
shell 十三問?

真的是不错,有些命令只知道使用,不知道它的原理,看了网中人的帖,才知道.
支持!!

2003-12-19 10:32 ohwww
shell 十三問?

好东西

2003-12-21 09:08 carrierye
shell 十三問?

期待ing

2003-12-21 22:15 horse
shell 十三問?

等待ing.

2003-12-22 03:31 網中人
shell 十三問?

4) " "(雙引號) 與 ' '(單引號)差在哪?

還是回到我們的 command line 來吧...
經過前面兩章的學習,應該很清楚當你在 shell prompt 後面敲打鍵盤、直到按下 Enter 的時候,
你輸入的文字就是 command line 了,然後 shell 才會以行程的方式執行你所交給它的命令。
但是,你又可知道:你在 command line 輸入的每一個文字,對 shell 來說,是有類別之分的呢?

簡單而言(我不敢說這是精確的定議,註一),command line 的每一個 charactor ,分為如下兩種:
* literal:也就是普通純文字,對 shell 來說沒特殊功能。
* meta:對 shell 來說,具有特定功能的特殊保留字元。
(註一:關於 bash shell 在處理 command line 時的順序說明,
請參考 O'Reilly 出版社之 Learning the Bash Shell, 2nd Edition,第 177 - 180 頁的說明,
尤其是 178 頁的流程圖 Figure 7-1 ... )

Literal 沒甚麼好談的,凡舉 abcd、123456 這些"文字"都是 literal ... (easy?)
但 meta 卻常使我們困惑..... (confused?)
事實上,前兩章我們在 command line 中已碰到兩個機乎每次都會碰到的 meta :
* IFS:由 <space> 或 <tab> 或 <enter> 三者之一組成(我們常用 space )。
* CR:由 <enter> 產生。
IFS 是用來拆解 command line 的每一個詞(word)用的,因為 shell command line 是按詞來處理的。
而 CR 則是用來結束 command line 用的,這也是為何我們敲 <enter> 命令就會跑的原因。
除了 IFS 與 CR ,常用的 meta 還有:
= :  設定變量。
$ :  作變量或運算替換(請不要與 shell prompt 搞混了)。
> :重導向 stdout。
< :重導向 stdin。
|:命令管線。
& :重導向 file descriptor ,或將命令置於背境執行。
( ):將其內的命令置於 nested subshell 執行,或用於運算或命令替換。
{ }:將其內的命令置於 non-named function 中執行,或用在變量替換的界定範圍。
; :在前一個命令結束時,而忽略其返回值,繼續執行下一個命令。
&& :在前一個命令結束時,若返回值為 true,繼續執行下一個命令。
|| :在前一個命令結束時,若返回值為 false,繼續執行下一個命令。
!:執行 history 列表中的命令
....

假如我們需要在 command line 中將這些保留字元的功能關閉的話,就需要 quoting 處理了。
在 bash 中,常用的 quoting 有如下三種方法:
* hard quote:' ' (單引號),凡在 hard quote 中的所有 meta 均被關閉。
* soft quote: " " (雙引號),在 soft quoe 中大部份 meta 都會被關閉,但某些則保留(如 $ )。(註二)
* escape : \ (反斜線),只有緊接在 escape (跳脫字符)之後的單一 meta 才被關閉。
( 註二:在 soft quote 中被豁免的具體 meta 清單,我不完全知道,
有待大家補充,或透過實作來發現及理解。 )

下面的例子將有助於我們對 quoting 的了解:
[code]        $ A=B C        # 空白鍵未被關掉,作為 IFS 處理。
        $ C: command not found.
        $ echo $A
       
        $ A="B C"        # 空白鍵已被關掉,僅作為空白鍵處理。
        $ echo $A
        B C[/code]
在第一次設定 A 變量時,由於空白鍵沒被關閉,command line 將被解讀為:
* A=B 然後碰到<IFS>,再執行 C 命令
在第二次設定  A 變量時,由於空白鍵被置於 soft quote 中,因此被關閉,不再作為 IFS :
* A=B<space>C
事實上,空白鍵無論在 soft quote 還是在 hard quote 中,均會被關閉。Enter 鍵亦然:
[code]        $ A='B
        > C
        > '
        $ echo "$A"
        B
        C[/code]
在上例中,由於 <enter> 被置於 hard quote 當中,因此不再作為 CR 字符來處理。
這裡的 <enter> 單純只是一個斷行符號(new-line)而已,由於 command line 並沒得到 CR 字符,
因此進入第二個 shell prompt (PS2,以 > 符號表示),command line 並不會結束,
直到第三行,我們輸入的 <enter> 並不在  hard quote 裡面,因此並沒被關閉,
此時,command line 碰到 CR 字符,於是結束、交給 shell 來處理。

上例的 <enter> 要是被置於 soft quote 中的話, CR 也會同樣被關閉:
[code]        $ A="B
        > C
        > "
        $ echo $A
        B C[/code]
然而,由於 echo $A 時的變量沒至於 soft quote 中,因此當變量替換完成後並作命令行重組時,<enter> 會被解釋為 IFS ,而不是解釋為 New Line 字符。

同樣的,用 escape 亦可關閉 CR 字符:
[code]        $ A=B\
        > C\
        >
        $ echo $A
        BC[/code]
上例中,第一個 <enter> 跟第二個 <enter> 均被 escape 字符關閉了,因此也不作為 CR 來處理,
但第三個 <enter> 由於沒被跳脫,因此作為 CR 結束 command line 。
但由於 <enter> 鍵本身在 shell meta 中的特殊性,在 \ 跳脫後面,僅僅取消其 CR 功能,而不會保留其 IFS 功能。

您或許發現光是一個 <enter> 鍵所產生的字符就有可能是如下這些可能:
CR
IFS
NL(New Line)
FF(Form Feed)
NULL
...
至於甚麼時候會解釋為甚麼字符,這個我就沒去深挖了,或是留給讀者諸君自行慢慢摸索了... ^_^

至於 soft quote 跟 hard quote 的不同,主要是對於某些 meta 的關閉與否,以 $ 來作說明:
[code]        $ A=B\ C
        $ echo "$A"
        B C
        $ echo '$A'
        $A[/code]
在第一個 echo 命令行中,$ 被置於 soft quote 中,將不被關閉,因此繼續處理變量替換,
因此 echo 將 A 的變量值輸出到熒幕,也就得到  "B C" 的結果。
在第二個 echo 命令行中,$ 被置於 hard quote 中,則被關閉,因此 $ 只是一個 $ 符號,
並不會用來作變量替換處理,因此結果是 $ 符號後面接一個 A 字母:$A 。

--------------------------------------
練習與思考:如下結果為何不同?
[code]        $ A=B\ C
        $ echo '"$A"'        # 最外面的是單引號
        "$A"
        $ echo "'$A'"        # 最外面的是雙引號
        'B C'
        (提示:單引號及雙引號,在 quoting 中均被關閉了。)[/code]
--------------------------------------

在 CU 的 shell 版裡,我發現有很多初學者的問題,都與 quoting 理解的有關。
比方說,若我們在 awk 或 sed 的命令參數中調用之前設定的一些變量時,常會問及為何不能的問題。
要解決這些問題,關鍵點就是:
* 區分出 shell meta 與 command meta

前面我們提到的那些 meta ,都是在 command line 中有特殊用途的,
比方說 { } 是將其內一系列 command line 置於不具名的函式中執行(可簡單視為 command block ),
但是,awk 卻需要用 { } 來區分出 awk 的命令區段(BEGIN, MAIN, END)。
若你在 command line 中如此輸入:
[code]$ awk {print $0} 1.txt[/code]
由於  { } 在 shell 中並沒關閉,那 shell 就將 {print $0} 視為 command block ,
但同時又沒有" ; "符號作命令區隔,因此就出現 awk 的語法錯誤結果。

要解決之,可用 hard quote :
[code]$ awk '{print $0}' 1.txt[/code]
上面的 hard quote 應好理解,就是將原本的 {、<space>、$(註三)、} 這幾個 shell meta 關閉,
避免掉在 shell 中遭到處理,而完整的成為 awk 參數中的 command meta 。
( 註三:而其中的 $0 是 awk 內建的 field number ,而非  awk 的變量,
awk 自身的變量無需使用 $ 。)
要是理解了 hard quote 的功能,再來理解 soft quote 與 escape 就不難:
[code]awk "{print \$0}" 1.txt
awk \{print\ \$0\} 1.txt[/code]

然而,若你要改變 awk 的 $0 的 0 值是從另一個 shell 變量讀進呢?
比方說:已有變量 $A 的值是 0 ,那如何在 command line 中解決 awk 的 $$A 呢?
你可以很直接否定掉 hard quoe 的方案:
[code]$ awk '{print $$A}' 1.txt[/code]
那是因為 $A 的 $ 在 hard quote 中是不能替換變量的。

聰明的讀者(如你!),經過本章學習,我想,應該可以解釋為何我們可以使用如下操作了吧:
[code]A=0
awk "{print \$$A}" 1.txt
awk \{print\ \$$A\} 1.txt
awk '{print $'$A'}' 1.txt
awk '{print $'"$A"'}' 1.txt     # 注:"$A" 包在 soft quote 中[/code]

或許,你能舉出更多的方案呢....  ^_^

--------------------------------------
練習與思考:請運用本章學到的知識分析如下兩串討論:
[url]http://bbs.chinaunix.net/forum/viewtopic.php?t=207178[/url]
[url]http://bbs.chinaunix.net/forum/viewtopic.php?t=216729[/url]
--------------------------------------

[[i] 本帖最后由 網中人 于 2008-10-30 02:07 编辑 [/i]]

2003-12-22 11:26 黑骏马
shell 十三問?

awk '{print $'$A'}' 1.txt
awk '{print $'"$A"'}' 1.txt     # 注:"$A" 包在 soft quote 中
请问网中人兄:
   这两行怎么解释执行的?

2003-12-22 14:36 網中人
shell 十三問?

你只要抓到並解讀出如下這兩段 hard quote 就能理解了:
'{print $'
'}'

2003-12-22 15:03 黑骏马
shell 十三問?

网中人兄:
对呀 ,我研究了这篇文章一上午,中午吃了饭就来看,整整看了五面,
明白了,把第一个和第二个'看成一起后面两个看成一起.
谢谢!!

2003-12-22 16:01 黑骏马
shell 十三問?

IFS=;
看了很多贴子,感觉IFS的概念有点模糊,理解能力差了.

2003-12-22 16:11 網中人
shell 十三問?

上面的 IFS=; 其實就是:
IFS=
將值設為 null
然後補一個" ; " 的 meta ...

昨晚的文章,一開始就提到 IFS 的作用了:
是 breaks command line down to each word 用的...
而 command line 則是 processes word by word 進行的,
若碰到 meta 或 key words ,會先處理之,等到所有的 words 都處理完畢,
那才開始傳給 shell 處理...

man bash 在 Special Parameters 那節有提到:
[code]       *      Expands to the positional parameters, starting from
              one.   When  the  expansion  occurs  within  double
              quotes,  it expands to a single word with the value
              of each parameter separated by the first  character
              of  the  IFS  special  variable.   That is, "$*" is
              equivalent to "$1c$2c...", where  c  is  the  first
              character of the value of the IFS variable.  If IFS
              is unset, the parameters are separated  by  spaces.
              If  IFS  is null, the parameters are joined without
              intervening separators.[/code]

請理解最後一句的意思,你就能理解 IFS= 的意思...

2003-12-23 10:46 黑骏马
shell 十三問?

#cat 1.txt
    1      2
    3      4
#cat 1.txt|while read i;do echo "$i";done
1      2
3      4
也就是说,前面的空字符没有了?用IFS=;的大概意思就是用空字符来分段,对否?
#a="   abc"
#echo "$a"
    abc         #能够正常输出前面的空字符。
环境:sco 5.04
:oops:  :oops:  :oops:

页: 1 [2] 3 4 5 6 7 8 9 10 11
查看完整版本: shell 十三問?