天天看點

shell基礎五:輸入和輸出(echo,read,cat,管道,tee,重定向等)

下面的所有環境都在在REDHAT LINUX9下試驗的

在LINUX中,要使轉義符生效,需加參數-e

從echo的變量開始說起

如:e c h o指令輸出轉義符以及變量。

                                                                      # echo -e "/007your home is $HOME , you are connected on `tty`"

your home is /root , you are connected on /dev/pts/1

# echo -e "/ayour home is $HOME , you are connected on `tty`"

your home is /root , you are connected on /dev/pts/1

#

  本例中

/007或/a你可以讓終端鈴響一聲

顯示出$ H O M E目錄,

并且可以讓系統執行t t y指令(注意,該指令用鍵盤左上角的符号,法語中的抑音符引起來,不是單引号 )。 在e c h o指令輸出之後附加換行,可以使用/ n選項:

                                                                      $ cat echod

#!/bin/sh

echo -e "this echo's 3 new lines/n/n/n"

echo "OK" 編輯一個新echod,如上内容,然後運作輸出如下:

                                                                      $ ./echod

this echo's 3 new lines

OK

$ 在e c h o語句中使用跳格符,記住别忘了加反斜杠/:

                                                                      $ echo -e "here is a tab/there are two tabs/t/tok"

here is a tab   here are two tabs               ok

$ 把一個字元串輸出到檔案中,使用重定向符号>。

在下面的例子中一個字元串被重定向到一個名為m y f i l e的檔案中:

                                                                      $ echo "The log files have all been done"> myfile 或者可以追加到一個檔案的末尾,這意味着不覆寫原有的内容:

                                                                      $ echo "$LOGNAME carried them out at `date`">>myfile 現在讓我們看一下m y f i l e檔案中的内容:

  The log files have all been done

sam carried them out at 六 11月 13 12:54:32 CST 2004 引号是一個特殊字元,是以必須要使用反斜杠/來使s h e l l忽略它的特殊含義。

假設你希望使用e c h o指令輸出這樣的字元串:“/ d e v / r m t 0”,那麼我們隻要在引号前面加上反斜杠/即可:

                                                                      $ echo "/"/dev/rmt0"/"

"/dev/rmt0"

$

read的用法,這是在"man bash"中的一段

                                                                      read [-ers] [-u fd] [-t timeout] [-a aname] [-p prompt] [-n nchars] [-d delim] [name ...]

    One  line  is  read  from  the  standard input, or from the file descriptor fd supplied as an argument to the -u option, and  the first word is assigned to the first name, the second word to the second name, and so on, with leftover words and their  intervening  separators  assigned  to the last name.  If there are fewer words read from the input stream than names, the remaining names are  assigned  empty  values.  The characters in IFS are used to split the line into words.  The backslash character (/)  may  be used  to  remove any special meaning for the next character read and for line continuation.  Options, if supplied, have the  following meanings:

    -a aname

    The words are assigned to sequential indices of the array variable aname, starting at 0.  aname is unset before any new  values  are  assigned.   Other  name  arguments  are ignored.

    -d delim

    The first character of delim is  used  to  terminate  the input line, rather than newline.

    -e     If the standard input is coming from a terminal, readline (see READLINE above) is used to obtain the line.

    -n nchars

    read returns after reading nchars characters rather  than waiting for a complete line of input.

    -p prompt

    Display prompt on standard error, without a trailing newline, before attempting to read any input.  The prompt is displayed only if input is coming from a terminal.

   -r     Backslash does not act as an escape character.  The backslash is considered to be part of the line.  In  particular,  a  backslash-newline pair may not be used as a line continuation.

   -s     Silent mode.  If input is coming from a terminal, characters are not echoed.

   -t timeout

   Cause  read  to time out and return failure if a complete line of input is not read within timeout  seconds.  This option  has  no  effect if read is not reading input from the terminal or a pipe.

    -u fd  Read input from file descriptor fd.

    If no names are supplied, the line read is assigned to the ariable  REPLY.   The  return  code  is zero, unless end-of-file is ncountered, read times out, or an invalid  file  descriptor  is supplied as the argument to -u. 經測試發現許多shell資料中沒有介紹過的新内容,或許地球人都知道了^_^,不管怎樣希望有興趣的一起琢磨一下。

以下是我用來測試的代碼,結果已經略去,請大家自行測試。

                                                                      read -p "how old r u? " age

echo $age

read -p "some words? " -a words

echo ${words[*]}

read -p "Password: " -s passwd                                 

echo $passwd 

read -t 5 auth

echo $auth

read -n 1 key

read -dq -p "input something end with q: " menu

read -e file #在這試試指令曆史和補齊功能

其它:可以自己練習

                                                                      [[email protected] sam]$ read name

sam

[[email protected] sam]$ echo $name

sam

[[email protected] sam]$ read name surname

sam ch

[[email protected] sam]$ echo $name surname

sam surname

[[email protected] sam]$ read name surname

sam ch yiir

[[email protected] sam]$ echo $name

sam

[[email protected] sam]$ echo $surname

ch yiir

                                                                      [[email protected] sam]$ cat var_test

#!/bin/sh

#var_test

echo -e "First Name :/c"

read name

echo -e "Middle Name :/c"

read middle

echo -e "Last name :/c"

read surname var_test檔案内容如上

                                                                      [[email protected] sam]$ ./var_test

First Name :wing

Middle Name :er

Last Name:chenwy 運作var_test檔案

請問上面是不是把三個值賦給name,middle,surname三個變量了???

 

test:

  /home/lee#read a b c d

1 2 3 4

/home/lee#echo $a

1

/home/lee#echo $b

2

/home/lee#echo $c

3

/home/lee#echo $d

4

/home/lee#

cat:顯示檔案内容,建立檔案,還可以用它來顯示控制字元。

注意:在檔案分頁符處不會停下來;會一下顯示完整個檔案。是以,可以使用m o r e指令或把c a t指令的輸出通過管道傳遞到另外一個具有分頁功能的指令中,使用指令less file可實作相同的功能。

如下形式

                                                                      $ cat myfile | more

$ cat myfile | pg c a t指令的一般形式為:

                                                                      cat [options] filename1 ... filename2 ... 1、顯示名為m y f i l e的檔案:

                                                                      $ cat myfile 2、顯示m y f i l e 1、m y f i l e 2、m y f i l e 3這三個檔案,可以用:

                                                                      $ cat myfile1 myfile2 myfile3 3、建立一個包含上述三個檔案的内容,名為b i g f i l e的檔案,可以用輸出重定向到新檔案中:

                                                                      $ cat myfile1 myfile2 myfile3 > bigfile 4、如果cat的指令行中沒有參數,輸入的每一行都立刻被cat指令輸出到螢幕上,輸入完畢後按< C T R L - D >結束

                                                                      $ cat

Hello world 

Hello world  

<ctrl+d>

$ 5、建立檔案

                                                                      $cat >myfile

This is great

<ctrl-d>

$cat myfile

This is great cat:參數選項

使用方式:

                                                                      cat [-AbeEnstTuv] [--help] [--version] fileName 說明:把檔案串連接配接後傳到基本輸出(螢幕或加 > fileName 到另一個檔案) 

參數:

  -n 或 --number 由 1 開始對所有輸出的行數編号 

-b 或 --number-nonblank 和 -n 相似,隻不過對于空白行不編号 

-s 或 --squeeze-blank 當遇到有連續兩行以上的空白行,就代換為一行的空白行 

-v 或 --show-nonprinting 顯示非列印字元 例:

顯示時加上行号

                                                                      $cp /etc/httpd/conf/httpd /usr/sam 

$ cat -n httpd.conf 把 httpd.conf 的内容加上行号後輸入 httpd1.conf 這個檔案裡

                                                                      $cat -n httpd.conf > httpd1.conf 對檔案httpd.conf加上行号(空白不加)後顯示

                                                                      $ cat -b httpd.conf 把 textfile1 和 textfile2 的檔案内容加上行号(空白行不加)之後将内容附加到 textfile3 裡。

                                                                      $ cat -b textfile1 textfile2 >> textfile3 清空/etc/test.txt檔案内容

                                                                      $cat /dev/null > /etc/test.txt 使用 sed 與 cat 除去空白行

                                                                      $ cat -s /etc/X11/XF86Config | sed '/^[[:space:]]*$/d' -s項我試了一下,不成功,不知是不是用錯了

其它參數來自:(這個我沒試)

http://bbs.chinaunix.net/forum/viewtopic.php?t=438463&highlight=cat

cat 還可以在您檢視包含如制表符這樣的非列印字元的檔案時起幫助作用。您可以用以下選項來顯示制表符:

  * -T 将制表符顯示為 ^I 

* -v 顯示非列印字元,除了換行符和制表符,它們使用各自效果相當的“控制序列”。例如,當您處理一個在 Windows 系統中生成的檔案時,這個檔案将使用 Control-M(^M)來标記行的結束。對于代碼大于 127 的字元,它們的前面将會被加上 M-(表示“meta”),這與其它系統中在字元前面加上 Alt- 相當。 

* -E 在每一行的結束處添加美元符($)。 顯示非列印字元

                                                                      $ cat -t /etc/X11/XF86Config 

... 

# Multiple FontPath entries are allowed (they are concatenated together) 

# By default, Red Hat 6.0 and later now use a font server independent of 

# the X server to render fonts. 

^IFontPath^I"/usr/X11R6/lib/X11/fonts/TrueType" 

^IFontPath^I"unix/:7100" 

EndSection 

...

                                                                      $ cat -E /etc/X11/XF86Config 

... 

# Multiple FontPath entries are allowed (they are concatenated together)$ 

# By default, Red Hat 6.0 and later now use a font server independent of$ 

# the X server to render fonts.$ 

FontPath "/usr/X11R6/lib/X11/fonts/TrueType"$ 

FontPath "unix/:7100"$ 

EndSection$ 

...

                                                                      $ cat -v /etc/X11/XF86Config 

... 

^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@M-|M-8^X^@^@^@ 

P^@^O"M-X^O [email protected]^M^@^@^@M-^@^O"[email protected]^@M-8*^@ 

@M-^[email protected]|A([email protected])M-yM-|M-sM-*M-hW^A^@^@j^@ 

M-|M-sM-%[email protected]^@^B^@^@M-sM-+fM-^A= ^@ ^@ 

F^@^@ ^@M-9^@^H^@^@M-sM-$M-G^E([email protected]^? 

^IM-A5^@^@^D^@PM-^]M-^/X1M-H%^@^@^D^@tyM-G 

...

 

tee:讀取标準輸入的資料,并将其内容輸出成檔案。 

  語   法:tee [-ai][--help][--version][檔案…] 

  補充說明:tee指令會從标準輸入裝置讀取資料,将其内容輸出到标準輸出裝置,同時儲存成檔案。我們可利用tee把管道導入的資料存成檔案,甚至一次儲存數份檔案。 

  參   數:-a 附加到既有檔案的面,而非覆寫它。如果給予tee指令的檔案名稱已經存在,預設會覆寫該檔案的内容。加上此參數,資料會新增在該檔案内容的最面,而不會删除原先之内容。 

       -i 忽略中斷信号 

       --help 線上幫助 

       --version 顯示版本資訊 

  例一: 

  列出文本檔案slayers.story的内容,同時複制3份副本,檔案名稱分别為ss-copy1、ss-copy2、ss-copy3: 

  

                                                                      $ cat slayers.story |tee ss-copy1 ss-copy2 ss-copy3 例一: 把列出目前目錄,并把結果結到myfile裡

  

                                                                      $ls -l |tee myfile 管道:可以通過管道把一個指令的輸出傳遞給另一個指令作為輸入。管道用豎杠|表示。它的一般形式為:

                                                                      指令1 |指令2

其中|是管道符号。 上例就是 

 

标準輸入、輸出和錯誤

當我們在s h e l l中執行指令的時候,每個程序都和三個打開的檔案相聯系,并使用檔案描述符來引用這些檔案。由于檔案描述符不容易記憶, s h e l l同時也給出了相應的檔案名。

下面就是這些檔案描述符及它們通常所對應的檔案名:

  檔案檔案描述符

輸入檔案—标準輸入0:它是指令的輸入,預設是鍵盤,也可以是檔案或其他指令的輸出。

輸出檔案—标準輸出1:它是指令的輸出,預設是螢幕,也可以是檔案。

錯誤輸出檔案—标準錯誤2:這是指令錯誤的輸出,預設是螢幕,同樣也可以是檔案。 如果沒有特别指定檔案說明符,指令将使用預設的檔案說明符(你的螢幕,更确切地說是你的終端)。

系統中實際上有1 2個檔案描述符,但是正如我們在上表中所看到的, 0、1、2是标準輸入、輸出和錯誤。可以任意使用檔案描述符3到9。

在執行指令時,可以指定指令的标準輸入、輸出和錯誤,要實作這一點就需要使用檔案重定向。表5 - 1列出了最常用的重定向組合,并給出了相應的檔案描述符。

在對标準錯誤進行重定向時,必須要使用檔案描述符,但是對于标準輸入和輸出來說,這不是必需的。

                                                                      常用檔案重定向指令

command > filename 把把标準輸出重定向到一個新檔案中

command >> filename 把把标準輸出重定向到一個檔案中(追加)

command 1 > fielname 把把标準輸出重定向到一個檔案中

command > filename 2>&1 把把标準輸出和标準錯誤一起重定向到一個檔案中

command 2 > filename 把把标準錯誤重定向到一個檔案中

command 2 >> filename 把把标準輸出重定向到一個檔案中(追加)

command >> filename 2>&1 把把标準輸出和标準錯誤一起重定向到一個檔案中(追加)

command < filename >filename2 把c o m m a n d指令以f i l e n a m e檔案作為标準輸入,以f i l e n a m e 2檔案

作為标準輸出

command < filename 把c o m m a n d指令以f i l e n a m e檔案作為标準輸入

command << delimiter 把從标準輸入中讀入,直至遇到d e l i m i t e r分界符

command <&m 把把檔案描述符m作為标準輸入

command >&m 把把标準輸出重定向到檔案描述符m中

command <&- 把關閉标準輸入

exec:

e x e c指令可以用來替代目前s h e l l;換句話說,并沒有啟動子s h e l l。使用這一指令時任何現有環境都将會被清除,并重新啟動一個s h e l l。它的一般形式為:

exec command

其中的c o m m a n d通常是一個s h e l l腳本。

我所能夠想像得出的描述e x e c指令最貼切的說法就是:當這個腳本結束時,相應的會話可能就結束了。e x e c指令的一個常見用法就是在使用者的. p r o f i l e最後執行時,用它來執行一些用于增強安全性的腳本。如果使用者的輸入無效,該

s h e l l将被關閉,然後重新回到登入提示符。e x e c還常常被用來通過檔案描述符打開檔案。

e x e c在對檔案描述符進行操作的時候(也隻有在這時),它不會覆寫你目前的s h e l l。

可以看網中人《shell十三問》第六節:

6) exec 跟 source 差在哪? 

能把十三問一次性看完最好,不過對我來說還是有些難度,今天才弄清楚第四問,看了好久才明白,目前為止,看完1,2,3,4,及11

exec:

e x e c指令可以用來替代目前s h e l l;換句話說,并沒有啟動子s h e l l。使用這一指令時任何現有環境都将會被清除,并重新啟動一個s h e l l。它的一般形式為:

exec command

其中的c o m m a n d通常是一個s h e l l腳本。

e x e c在對檔案描述符進行操作的時候,它不會覆寫你目前的s h e l l。

source和exec的差別

1,我認為他們帶的參數是不一樣的

source通常是shell腳本,而exec不但可以把一個腳本當成參數,而且還可以把一個系統指令當參數,例如: exec ls

2,另外一個不同就是,exec任務執行完畢後,會執行類似logout的操作,而source執行完一個任務後傳回目前的shell.

3,還有,他們的用途也不是一樣的

 

在輸入輸出概念裡,内聯輸入重定向也是個很常用的用法,在自動FTP腳本裡、SHELL的生成器裡,wingger可以把它再加進來,搜集的過程就是一個非常好的學習過程!!! :P 

如:

                                                                      ftp -ni <<ENDOFSCRIPT

open 192.168.20.100

user username  pwd

bin

prom

cd /u

mput *

close

bye

ENDOFSCRIPT

  cat > mvfile.sh <</END

for i in `ls *.tar|sed -e 's//.tar//'`

do

      mkdir $i

      mv ${i}.tar $i

done

END