免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1793487 | 回复: 87
打印 上一主题 下一主题

[学习共享] shell 十三問? [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-12-09 02:48 |显示全部楼层 |倒序浏览
我在 CU 的日子並不長,有幸在 shell 版上與大家結緣。
除了跟眾前輩學習到不少技巧之外,也常看到不少朋友的問題。
然而,在眾多問題中,我發現許多瓶頸都源於 shell 的基礎而已。
每次要解說,卻總有千言萬語不知從何起之感...

這次,我不是來回答,而是準備了關於 shell 基礎的十三個問題要問大家﹗
希望 shell 學習者們能夠透過尋找答案的過程,好好的將 shell 基礎打紮實一點...
當然了,這些問題我也會逐一解說一遍。只是,我不敢保證甚麼時候能夠完成這趟任務。
除了時間關係外,個人功力實在有限,很怕匆忙間誤導觀眾就糟糕了。
若能拋磚引玉,誘得其他前輩出馬補充,那才真的是功德一件﹗

shell 十三問:

1) 為何叫做 shell ?
http://bbs.chinaunix.net/viewthr ... p;page=2#pid1454336
2) shell prompt(PS1) 與 Carriage Return(CR) 的關係? (2008-10-30 02:05 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=2#pid1467910
3) 別人 echo、你也 echo ,是問 echo 知多少?( 2008-10-30 02:08 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=3#pid1482452
4) " "(雙引號) 與 ' '(單引號)差在哪?  (2008-10-30 02:07 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=4#pid1511745
5) var=value?export 前後差在哪? (2008-10-30 02:12 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=5#pid1544391
6) exec 跟 source 差在哪? (2008-10-30 02:17 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=6#pid1583329
7) ( ) 與 { } 差在哪?
http://bbs.chinaunix.net/viewthr ... p;page=6#pid1595135
8) $(( )) 與 $( ) 還有${ } 差在哪? (2008-10-30 02:20 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=7#pid1617953
9) $@ 與 $* 差在哪?
http://bbs.chinaunix.net/viewthr ... p;page=7#pid1628522
10) && 與 || 差在哪? (2008-10-30 02:21 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=7#pid1634118
11) > 與 < 差在哪? (2008-10-30 02:24 最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=7#pid1636825
12) 你要 if 還是 case 呢? (2008-10-30 02:25最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=8#pid1679488
13) for what? while 與 until 差在哪? (2008-10-30 02:26最後更新)
http://bbs.chinaunix.net/viewthr ... p;page=8#pid1692457

補充問題:
b1) [^ ] 跟 [! ] 差在哪?
Part-I(Wildcard): (2008-10-30 02:25 最後更新)
http://bbs.chinaunix.net/viewthr ... ;page=16#pid2930144
Part-II(Regular Expression): (2008-10-30 02:26 最後更新)
http://bbs.chinaunix.net/viewthr ... ;page=16#pid2934852


--------------
說明:
1) 歡迎大家補充/擴充問題。
2) 我接觸電腦中文名稱時是在台灣,因此一些術語或與大陸不同,請自行轉換。
3) 我會不定時"逐題"說明(以 Linux 上的 bash 為環境)。同時,也會在任何時候進行無預警修改。請讀者自行留意。
4) 本人於本系列所發表的任文章均可自由以電子格式(非印刷)引用、修改、轉載,且不必註明出處(若能註明 CU 更佳)。
當然,若有錯漏或不當結果,本人也不負任何責任。
5) 若有人願意整理成冊且付印者,本人僅保留著作權,版權收益之 30% 須捐贈與 CU 論壇管理者,剩餘不究。

---------
建議參考討論:
1) shaoping0330 兄關於變量替換的補充:
(連結在改版後已經失效)

2) shaoping0330 兄關於 RE 的說明:
http://bbs.chinaunix.net/forum/viewtopic.php?t=393964

3) 關於 nested subshell 的討論:
(連結在改版後已經失效)

4) 關於 IFS 的討論:
http://bbs.chinaunix.net/forum/viewtopic.php?t=512925

---------
* 感謝 lkydeer 兄整理 word/pdf 版本方便大家参考:
http://bbs.chinaunix.net/viewthr ... &extra=page%3D2

[ 本帖最后由 網中人 于 2008-11-4 02:12 编辑 ]

评分

参与人数 2可用积分 +5 信誉积分 +5 收起 理由
substr函数 + 5 赞一个!
mocou + 5 精品文章

查看全部评分

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2003-12-09 14:12 |显示全部楼层

shell 十三問?

1) 為何叫做 shell ?

在介紹 shell 是甚麼東西之前,不妨讓我們重新檢視使用者與電腦系統的關係:
        圖(FIXME)

我們知道電腦的運作不能離開硬體,但使用者卻無法直接對硬體作驅動,
硬體的驅動只能透過一個稱為"作業系統(Operating System)"的軟體來控管,
事實上,我們每天所談的 linux ,嚴格來說只是一個作業系統,我們稱之為"核心(kernel)"。
然而,從使用者的角度來說,使用者也沒辦法直接操作 kernel ,
而是透過 kernel 的"外殼"程式,也就是所謂的 shell ,來與 kernel 溝通。
這也正是 kernel 跟 shell 的形像命名關係。如圖:
                圖(FIXME)

從技術角度來說,shell 是一個使用者與系統的互動界面(interface),
主要是讓使用者透過命令行(command line)來使用系統以完成工作。
因此,shell 的最簡單的定義就是---命令解譯器(Command Interpreter):
        * 將使用者的命令翻譯給核心處理,
        * 同時,將核心處理結果翻譯給使用者。

每次當我們完成系統登入(log in),我們就取得一個互動模式的 shell ,也稱為 login shell 或 primary shell。
若從行程(process)角度來說,我們在 shell 所下達的命令,均是 shell 所產生的子行程。這現像,我們暫可稱之為 fork 。
如果是執行腳本(shell script)的話,腳本中的命令則是由另外一個非互動模式的子 shell (sub shell)來執行的。
也就是 primary shell 產生 sub shell 的行程,sub shell 再產生 script 中所有命令的行程。
(關於行程,我們日後有機會再補充。)

這裡,我們必須知道:kernel 與 shell 是不同的兩套軟體,而且都是可以被替換的:
        * 不同的作業系統使用不同的 kernel ,
        * 而在同一個 kernel 之上,也可使用不同的 shell 。
在 linux 的預設系統中,通常都可以找到好幾種不同的 shell ,且通常會被列於如下檔案裡:
        /etc/shells
不同的 shell 有著不同的功能,且也彼此各異、或說"大同小異"。
常見的 shell 主要分為兩大主流:
        sh:
                burne shell (sh)
                burne again shell (bash)
        csh:
                c shell (csh)
                tc shell (tcsh)
                korn shell (ksh)
        (FIXME)

大部份的 Linux 系統的預設 shell 都是 bash ,其原因大致如下兩點:
        * 自由軟體
        * 功能強大
bash 是 gnu project 最成功的產品之一,自推出以來深受廣大 Unix 用戶喜愛,
且也逐漸成為不少組織的系統標準。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
3 [报告]
发表于 2003-12-11 17:30 |显示全部楼层

shell 十三問?

原帖由 "config t" 发表:
以前接触了一些台湾/香港软件和技术人员
其实并不是他们技术首先问题
而是他们很务实,简洁,而且最重要是应用得很适当,就是把一个简单的东西发挥它最大的用处

我最佩服他们这方面的思想


怎麼我在台灣的感覺剛好相反呢?  ^_^

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2003-12-12 02:55 |显示全部楼层

shell 十三問?

2) shell prompt(PS1) 與 Carriage Return(CR) 的關係?

當你成功登錄進一個文字界面之後,大部份情形下,
你會在熒幕上看到一個不斷閃爍的方塊或底線(視不同版本而別),
我們稱之為*遊標*(cursor)。
遊標的作用就是告訴你接下來你從鍵盤輸入的按鍵所插入的位置,
且每輸入一鍵遊標便向右邊移動一個格子,若連續輸入太多的話,則自動接在下一行輸入。

假如你剛完成登錄還沒輸入任何按鍵之前,你所看到的遊標所在位置的同一行的左邊部份,
我們稱之為*提示符號*(prompt)。
提示符號的格式或因不同系統版本而各有不同,在 Linux 上,只需留意最接近遊標的一個可見的提示符號,通常是如下兩者之一:
        $:給一般使用者帳號使用
        #:給 root (管理員)帳號使用

事實上,shell prompt 的意思很簡單:
        * 是 shell 告訴使用者:您現在可以輸入命令行了。
我們可以說,使用者只有在得到 shell prompt 才能打命令行,
而 cursor 是指示鍵盤在命令行所輸入的位置,使用者每輸入一個鍵,cursor 就往後移動一格,
直到碰到命令行讀進 CR(Carriage Return,由 Enter 鍵產生)字符為止。
CR 的意思也很簡單:
        * 是使用者告訴 shell:老兄你可以執行我的命令行了。
嚴格來說:
        * 所謂的命令行,就是在 shell prompt 與 CR 字符之間所輸入的文字。
        (思考:為何我們這裡堅持使用 CR 字符而不說 Enter 鍵呢?答案在後面的學習中揭曉。)

不同的命令可接受的命令行格式或有不同,一般情況下,一個標準的命令行格式為如下所列:
        command-name options argument

若從技術細節來看,shell 會依據 IFS(Internal Field Seperator) 將 command line 所輸入的文字給拆解為"字段"(word)。
然後再針對特殊字符(meta)先作處理,最後再重組整行 command line 。
(注意:請務必理解上兩句話的意思,我們日後的學習中會常回到這裡思考。)

其中的 IFS 是 shell 預設使用的欄位分隔符號,可以由一個及多個如下按鍵組成:
        * 空白鍵(White Space)
        * 表格鍵(Tab)
        * 回車鍵(Enter)

系統可接受的命令名稱(command-name)可以從如下途逕獲得:
        * 明確路逕所指定的外部命令
        * 命令別名(alias)
        * 自定功能(function)
        * shell 內建命令(built-in)
        * $PATH 之下的外部命令
每一個命令行均必需含用命令名稱,這是不能缺少的。

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

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
5 [报告]
发表于 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 我們日後有機會再解說,或可先參考如下討論:
http://www.chinaunix.net/forum/viewtopic.php?t=191375 )

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

  2. $
复制代码

你會發現只有一個空白行,然後又回到 shell prompt 上了。
這是因為 echo 在預設上,在顯示完 argument 之後,還會送出一個換行符號(new-line charactor)。
但是上面的 command 並沒任何的 argument ,那結果就只剩一個換行符號了...
若你要取消這個換行符號,可利用 echo 的 -n option :
  1. $ echo -n
  2. $
复制代码

不妨讓我們回到 command line 的概念上來討論上例的 echo 命令好了:
* command line 只有 command_name(echo) 及 option(-n),並沒有任何 argument 。
要想看看 echo 的 argument ,那還不簡單﹗接下來,你可試試如下的輸入:
  1. $ echo first line
  2. first line
  3. $ echo -n first line
  4. first line $
复制代码

於上兩個 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 的選項及控制字符:

例一:
  1. $ echo -e "a\tb\tc\nd\te\tf"
  2. a       b       c
  3. d       e       f
复制代码

上例運用 \t 來區隔 abc 還有 def ,及用 \n 將 def 換至下一行。

例二:
  1. $ echo -e "\141\011\142\011\143\012\144\011\145\011\146"
  2. a       b       c
  3. d       e       f
复制代码

與例一的結果一樣,只是使用 ASCII 八進位編碼。

例三:
  1. $ echo -e "\x61\x09\x62\x09\x63\x0a\x64\x09\x65\x09\x66"
  2. a       b       c
  3. d       e       f
复制代码

與例二差不多,只是這次換用 ASCII 十六進位編碼。

例四:
  1. $ echo -ne "a\tb\tc\nd\te\bf\a"
  2. a       b       c
  3. d       f $
复制代码

因為 e 字母後面是退格鍵(\b),因此輸出結果就沒有 e 了。
在結束時聽到一聲鈴嚮,那是 \a 的傑作﹗
由於同時使用了 -n 選項,因此 shell prompt 緊接在第二行之後。
若你不用 -n 的話,那你在 \a 後再加個 \c ,也是同樣的效果。

事實上,在日後的 shell 操作及 shell script 設計上,echo 命令是最常被使用的命令之一。
比方說,用 echo 來檢查變量值:
  1. $ A=B
  2. $ echo $A
  3. B
  4. $ echo $?
  5. 0
复制代码

(註:關於變量概念,我們留到下兩章才跟大家說明。)

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

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

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
6 [报告]
发表于 2003-12-17 08:11 |显示全部楼层

shell 十三問?

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

呵、、、 這是下一章的重點哦﹗  ^_^

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
7 [报告]
发表于 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 的了解:
  1.         $ A=B C        # 空白鍵未被關掉,作為 IFS 處理。
  2.         $ C: command not found.
  3.         $ echo $A
  4.        
  5.         $ A="B C"        # 空白鍵已被關掉,僅作為空白鍵處理。
  6.         $ echo $A
  7.         B C
复制代码

在第一次設定 A 變量時,由於空白鍵沒被關閉,command line 將被解讀為:
* A=B 然後碰到<IFS>,再執行 C 命令
在第二次設定  A 變量時,由於空白鍵被置於 soft quote 中,因此被關閉,不再作為 IFS :
* A=B<space>C
事實上,空白鍵無論在 soft quote 還是在 hard quote 中,均會被關閉。Enter 鍵亦然:
  1.         $ A='B
  2.         > C
  3.         > '
  4.         $ echo "$A"
  5.         B
  6.         C
复制代码

在上例中,由於 <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 也會同樣被關閉:
  1.         $ A="B
  2.         > C
  3.         > "
  4.         $ echo $A
  5.         B C
复制代码

然而,由於 echo $A 時的變量沒至於 soft quote 中,因此當變量替換完成後並作命令行重組時,<enter> 會被解釋為 IFS ,而不是解釋為 New Line 字符。

同樣的,用 escape 亦可關閉 CR 字符:
  1.         $ A=B\
  2.         > C\
  3.         >
  4.         $ echo $A
  5.         BC
复制代码

上例中,第一個 <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 的關閉與否,以 $ 來作說明:
  1.         $ A=B\ C
  2.         $ echo "$A"
  3.         B C
  4.         $ echo '$A'
  5.         $A
复制代码

在第一個 echo 命令行中,$ 被置於 soft quote 中,將不被關閉,因此繼續處理變量替換,
因此 echo 將 A 的變量值輸出到熒幕,也就得到  "B C" 的結果。
在第二個 echo 命令行中,$ 被置於 hard quote 中,則被關閉,因此 $ 只是一個 $ 符號,
並不會用來作變量替換處理,因此結果是 $ 符號後面接一個 A 字母:$A 。

--------------------------------------
練習與思考:如下結果為何不同?
  1.         $ A=B\ C
  2.         $ echo '"$A"'        # 最外面的是單引號
  3.         "$A"
  4.         $ echo "'$A'"        # 最外面的是雙引號
  5.         'B C'
  6.         (提示:單引號及雙引號,在 quoting 中均被關閉了。)
复制代码

--------------------------------------

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

前面我們提到的那些 meta ,都是在 command line 中有特殊用途的,
比方說 { } 是將其內一系列 command line 置於不具名的函式中執行(可簡單視為 command block ),
但是,awk 卻需要用 { } 來區分出 awk 的命令區段(BEGIN, MAIN, END)。
若你在 command line 中如此輸入:
  1. $ awk {print $0} 1.txt
复制代码

由於  { } 在 shell 中並沒關閉,那 shell 就將 {print $0} 視為 command block ,
但同時又沒有" ; "符號作命令區隔,因此就出現 awk 的語法錯誤結果。

要解決之,可用 hard quote :
  1. $ awk '{print $0}' 1.txt
复制代码

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


然而,若你要改變 awk 的 $0 的 0 值是從另一個 shell 變量讀進呢?
比方說:已有變量 $A 的值是 0 ,那如何在 command line 中解決 awk 的 $$A 呢?
你可以很直接否定掉 hard quoe 的方案:
  1. $ awk '{print $$A}' 1.txt
复制代码

那是因為 $A 的 $ 在 hard quote 中是不能替換變量的。

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


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

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

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

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
8 [报告]
发表于 2003-12-22 14:36 |显示全部楼层

shell 十三問?

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

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
9 [报告]
发表于 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 那節有提到:
  1.        *      Expands to the positional parameters, starting from
  2.               one.   When  the  expansion  occurs  within  double
  3.               quotes,  it expands to a single word with the value
  4.               of each parameter separated by the first  character
  5.               of  the  IFS  special  variable.   That is, "$*" is
  6.               equivalent to "$1c$2c...", where  c  is  the  first
  7.               character of the value of the IFS variable.  If IFS
  8.               is unset, the parameters are separated  by  spaces.
  9.               If  IFS  is null, the parameters are joined without
  10.               intervening separators.
复制代码


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

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2003-12-23 14:04 |显示全部楼层

shell 十三問?

IFS=; 其實就是 IFS=
請記著﹗

當 IFS 為 null 時,在 $* (也就是 positional parameter)將被視為單一的 word ,因為跟本沒區隔嘛(想想 IFS 作啥用?)....
a=" abc"
之後,若 IFS 沒改變的話,那下面兩行是有差別的:
echo $a
echo "$a"
差別就在 quoting ! (自己再想想 space 在 soft quote 是否為 IFS ?)

若 IFS=
再跑上兩行 echo ,那就沒差了,
因為不管 space 在 quoting 內還是外,都不是 IFS ﹗
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP