隨筆-314  評論-209  文章-0  trackbacks-0
           
          我們從一個用戶請求開始講,ORACLE的完整的工作機制是怎樣的,首先一個用戶進程發出一個連接請求,如果使用的是主機命名或者是本地服務命中的主機名使用的是機器名(非IP地址),那么這個請求都會通過DNS服務器或HOST文件的服務名解析然后傳送到ORACLE監聽進程,監聽進程接收到用戶請求后會采取兩種方式來處理這個用戶請求,下面我們分專用服務器和共享服務器分別采用這兩種方式時的情況來講:

              專用服務器模式下:一種方式是監聽進程接收到用戶進程請求后,產生一個新的專用服務器進程,并且將對用戶進程的所有控制信息傳給此服務器進程,也就是說新建的服務器進程繼承了監聽進程的信息,然后服務器進程給用戶進程發一個RESEND包,通知用戶進程可以開始給它發信息了,用戶進程給這個新建的服務器進程發一個CONNECT包,服務器進程再以ACCEPT包回應用戶進程,致此,用戶進程正式與服務器進程確定連接。我們把這種連接叫做HAND-OFF連接,也叫轉換連接。另一種方式是監聽進程接收到用戶進程的請求后產生一個新的專用服務器進程,這個服務器進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監聽進程,監聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給服務器進程發送一個CONNECT包,服務器進程再給用戶進程發送一個ACCEPT包,致此,用戶進程可以正式向服務器進程發送信息了。這種方式我們叫做重定向連接。HAND-OFF連接需要系統平臺具有進程繼承的能力,為了使WINDOWS NT/2000支持HAND-OFF必須在HKEY_LOCAL_MACHINE>SOFTWARE>ORACLE>HOMEX中設置USE_SHARED_SOCKET。

              共享服務器模式下:只有重定向連接的方式,工作方式是監聽進程接收到用戶進程的請求后產生一個新的調度進程,這個調度進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監聽進程,監聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給調度進程發送一個CONNECT包,調度進程再給用戶進程發送一個ACCEPT包,致此,用戶進程可以正式向調度進程發送信息了。可以通過設置MAX_DISPIATCHERS這個參數來確定調度進程的最大數目,如果調度進程的個數已經達到了最大,或者已有的調度進程不是滿負荷,監聽進程將不再創建新的調度進程,而是讓其中一個調度進程選用一個TCP/IP端口來與此用戶進程交互。調度進程每接收一個用戶進程請求都會在監聽進程處作一個登記,以便監聽進程能夠均衡每個調度進程的負荷,所有的用戶進程請求將分別在有限的調度進程中排隊,所有調度進程再順序的把各自隊列中的部分用戶進程請求放入同一個請求隊列,等候多個ORACLE的共享服務器進程進行處理(可以通過SHARED_SERVERS參數設置共享服務器進程的個數),也就是說所有的調度進程共享同一個請求隊列,共享服務器模式下一個實例只有一個請求隊列,共享服務器進程處理完用戶進程的請求后將根據用戶進程請求取自不同的調度進程將返回結果放入不同的響應隊列,也就是說有多少調度進程就有多少響應隊列,然后各個調度進程從各自的響應隊列中將結果取出再返回給用戶進程。

              以上我們講完了用戶與ORACLE的連接方式,下面我們要講ORACLE服務器進程如可處理用戶進程的請求,當一個用戶進程發出了一條SQL語名:UPDATE TABBLEA SET SALARY=SALARY*2;首先,服務器進程把這條語句的字符轉換成ASCII等效數字碼,接著這個ASCII碼被傳遞給一個HASH函數,并返回一個HASH值,服務器進程將到SHARED POOL 的共享PL/SQL區去查找是否存在同樣的HASH值,如果存在,服務器進程將使用這條語句已高速緩存在SHARED POOL中的已分析過的版本來執行,如果不存在,服務器進程將對該語句進行語法分析,首先檢查該語句的語法的正確性,接著對語句中涉及的表、索引、視圖等對象進行解析,并對照數據字典檢查這些對象的名稱以及相關結構,并根據ORACLE選用的優化模式以及數據字典中是否存在相應對象的統計數據和是否使用了存儲大綱來生成一個執行計劃或從存儲大綱中選用一個執行計劃,然后再用數據字典核對此用戶對相應對象的執行權限,最后生成一個編譯代碼。ORACLE將這條語名的本身實際文本、HASH值、編譯代碼、與此語名相關聯的任何統計數據和該語句的執行計劃緩存在SHARED POOL的共享PL/SQL區。服務器進程通過SHARED POOL 鎖存器來申請可以向哪些共享PL/SQL區中緩存這此內容,也就是說被SHARED POOL鎖存器鎖定的PL/SQL區中的塊不可被覆蓋,因為這些塊可能被其它進程所使用。在SQL分析階段將用到LIBRARY CACHE,從數據字典中核對表、視圖等結構的時候,需要將數據字典從磁盤讀入LIBRARY CACHE,因此,在讀入之前也要使用LIBRARY CACHE鎖存器來申請用于緩存數據字典。

              生成編譯代碼之后,接著下一步服務器進程要準備開始更新數據,服務器進程將到DB BUFFER中查找是否有相關對象的緩存數據,下面分兩個可能進行解釋:

              如果沒有,服務器進程將在表頭部請求一些行鎖,如果成功加鎖,服務器進程將從數據文件中讀這些行所在的數據塊放入DB BUFFER中空閑的區域或者覆蓋已被擠出LRU列表的非臟數據塊緩沖區,并且排列在LRU列表的頭部,如果這些非臟數據緩沖區寫完也不能滿足新數據的請求時,會立即觸發DBWN進程將臟數據列表中指向的緩沖塊寫入數據文件,并且清洗掉這些緩沖區,來騰出空間緩沖新讀入的數據,也就是在放入DB BUFFER之前也是要先申請DB BUFFER中的鎖存器,成功鎖定后,再寫入DB BUFFER,然后服務器程將該語句影響的被讀入DB BUFFER塊中的這些行的ROWID及將要更新的原值和新值及SCN等信息逐條的寫入REDO LOG BUFFER,在寫入REDO LOG BUFFER之前也是先請求REDO LOG BUFFER塊的鎖存器,成功鎖定之后才開始寫入,當寫入達到REDO LOG BUFFER大小的三分之一或寫入量達到1M或超過三秒后或發生檢查點時或者DBWN之前發生,LGWR將把REDO LOG BUFFER中的數據寫入磁盤上的重做日志文件,已被寫入重做日志文件的REDO LOG BUFFER中的塊上的鎖存器被釋放,并可被后來寫入的信息所覆蓋,REDO LOG BUFFER以循環的方式工作。當一個重做日志文件寫滿后,LGWR將切換到下一個重做日志文件,如果是歸檔模式,歸檔進程還將前一個寫滿的重做日志進程寫入歸檔日志文件,重做日志文件也是循環工作方式。寫完所有的REDO LOG BUFFER之后,服務器進程開始改寫這個DB BUFFER塊頭部的事務列表并寫入SCN,然后COPY包含這個塊的頭部事務列表及SCN信息的數據副本放入回滾段中,我們將回滾段中的副本稱為數據塊的“前映像”。(回滾段可以存儲在專門的回滾表空間中,這個表空間由一個或多個物理文件組成,并專用于回滾表空間,回滾段也可在其它表空間中的數據文件中開辟。)然后改寫這個DB BUFFER塊的數據,并在其頭部寫入對應的回滾段地址,如果對一行數據多次UPDATE而不COMMIT則在回滾段中將會有多個“前映像”,除第一個“前映像”含有SCN信息外,其它的每個“前映像”的頭部還含有SCN信息和“前前映像”的回滾段地址。一次UPDATE操作只對應一個SCN。然后服務器進程在臟數據列表中建立一條指向此緩沖塊的指針。接著服務器進程會從數據文件讀入第二個塊重復以上讀入,記日志,建立回滾段,修改,放入臟列表的動作,當臟數據列表達到一定長度時,DBWN進程將臟數據列表中指向的緩沖塊全部寫入數據文件,也就是釋放加在這些DB BUFER 塊上的鎖存器。其實ORACLE可以一次從數據文件中讀入幾個塊放入DB BUFFER,可以通過參數DB_FILE_MULTIBLOCK_READ_COUNT來設置一次讀入的塊的個數。

              如果要查找的數據已緩存,則根據用戶的SQL操作類型決定如何操作,如果是SELECT 則查看DB BUFFER塊的頭部是否有事務,如果有,將從回滾段讀取,如果沒有則比較SELECT 的SCN與DB BUFFER塊頭部的SCN如果比自己大,仍然從回滾段讀取,如果比自己小則認這是一個非臟緩存,可以直接從這個DB BUFFER塊中讀取。如果是UPDATE則即使在DB BUFFER中找到一個沒有事務,而且SCN比自己小的非臟緩存數據塊,服務器進程仍然要到表的頭部對這條記錄申請加鎖,加鎖成功則進行后續動作,如果不成功,則要等待前面的進程解鎖后才能進行動作。

              只有當SQL語句影響的所有行所在的最后一個塊被讀入DB BUFFER并且重做信息被寫入REDO LOG BUFFER(僅是指重做日志緩沖,而非重做日志文件)之后,用戶才可以發出COMMIT,COMMIT觸發LGRW,但并不強制立即DBWN來釋放所有相應的DB BUFFER塊上的鎖,也就是說有可能出現已COMMIT,但在隨后的一段時間內DBWN還在寫這條語句涉及的數據塊的情形,表頭部的行鎖,并不是在COMMIT一發出就馬上釋放,實際上要等到相應的DBWN進程結束才會釋放。一個用戶請求鎖定另一個用戶已COMMIT的資源不成功的機會是存在的,從COMMIT到DBWN進程結束之間的時間很短,如果恰巧在這個時間斷電,由于COMMIT已觸發LGWR進程,所以這些未來得及寫入數據文件的改變會在實例重啟后由SMON進程根據重做日志文件來前滾。如果未COMMIT就斷電,由于DBWN之前觸發LGWR,所有DBWN在數據文件上的修改都會被先一步記入重做日志文件,實例重啟后,SMON進程再根據重做日志文件來回滾。

              如果用戶ROOLBACK,則服務器進程會根據數據文件塊和DB BUFFER中塊的頭部的事務列表和SCN以及回滾段地址找到回滾段中相應的修改前的副本,并且用這些原值來還原當前數據文件中已修改但未提交的改變。如果有多個“前映像”,服務器進程會在一個“前映像”的頭部找到“前前映像”的回滾段地址,一直找到同一事務下的最早的一個“前映像”為止。一旦發出了COMMIT,用戶就不能ROOLBACK,這使得COMMIT后DBWN進程還沒有全部完成的后續動作得到了保障。

              下面我們要提到檢查點的作用,當一個全部檢查點發生的時候,首先讓LGWR進程將REDO LOG BUFFER中的所有緩沖(包含未提交的重做信息)寫入重做日志文件,然后讓DBWN進程將DB BUFFER中所有已提交的緩沖寫入數據文件(不強制寫未提交的)。然后更新控制文件和數據文件頭部的SCN,表明當前數據庫是一致的,如果在發生檢點之前斷電,并且當時有一個未提交的改變正在進行,實例重啟之后,SMON進程將從上一個檢查點開始核對這個檢查點之后記錄在重做日志文件中已提交的和未提交改變,因為DBWN之前會觸發LGWR,所以DBWN對數據文件的修改一定會被先記錄在重做日志文件中。因此,斷電前被DBWN寫進數據文件的改變將通過重做日志文件中的記錄進行還原,叫做回滾,如果斷電時有一個已提交,但DBWN動作還沒有完全完成的改變存在,因為已經提交,提交會觸發LGWR進程,所以不管DBWN動作是否已完成,該語句將要影響的行及其產生的結果一定已經記錄在重做日志文件中了,則實例重啟后,SMON進程根據重做日志文件進行前滾。由此可見,實例失敗后用于恢復的時間由兩個檢查點之間的間隔大小來決定,我們可以通個四個參數設置檢查點執行的頻率,LOG_CHECKPOINT_IMTERVAL決定了兩個檢查點之間寫入重做日志文件的系統物理塊的大小,LOG_CHECKPOINT_TIMEOUT決定了兩個檢查點之間的時間長度,FAST_START_IO_TARGET決定了用于恢復時需要處理的塊的大小,FAST_START_MTTR_TARGET直接決定了用于恢復的時間的長短。SMON進程執行的前滾和回滾與用戶的回滾是不同的,SMON是根據重做日志文件進行前滾或回滾,而用戶的回滾一定是根據回滾段的內容進行回滾的。在這里我們要說一下回滾段存儲的數據,假如是delete操作,則回滾段將會記錄整個行的數據,假如是update,則回滾段只記錄被修改了的字段的變化前的數據(前映像),也就是沒有被修改的字段是不會被記錄的,假如是insert,則回滾段只記錄插入記錄的rowid。這樣假如事務提交,那回滾段中簡單標記該事務已經提交;假如是回退,則如果操作是是delete,回退的時候把回滾段中數據重新寫回數據塊,操作如果是update,則把變化前數據修改回去,操作如果是insert,則根據記錄的rowid 把該記錄刪除。

              下面我們要講DBWN如何來寫數據文件,在寫數據文件前首先要找到可寫的空閑數據塊,ORACLE中空閑數據塊可以通過FREELIST或BITMAP來維護,它們位于一個段的頭部用來標識當前段中哪些數據塊可以進行INSERT。在本地管理表空間中ORACLE自動管理分配給段的區的大小,區的分配信息存儲在組成表空間的數據文件的頭部,而數據字典管理的表空間用戶可以在創建時決定區的大小,并且區的分配信息是存儲在數據字典中的,只在本地管理的表空間中才能選用段自動管理,采用自動段空間管理的本地管理表空間中的段中的空閑數據塊的信息就存放在段的頭部并且使用位圖來管理,采用手動管理的本地管理表空間中的段和數據字典管理的表空間中的段中的空閑數據塊的管理都使用位于段頭部的空閑列表來管理,空閑列表的工作方式:首先一個空的數據塊被加入空閑列表,當其中空閑空間小于PCTFREE設置的值之后,這個塊從空閑列表刪除,當這個塊中的內容降至PCTUSED設置的值之下后,這個數據塊被再次加入空閑列表,位于空閑列表中的數據塊都是可以向其中INSERT的塊,當一個塊移出了空閑列表,但只要其中還有保留空間就可以進行UPDATE,當對其中一行UPDATE一個大數據時,如果當前塊不能完全放下整個行,只會把整個行遷移到一個新的數據塊,并在原塊位置留下一個指向新塊的指針,這叫行遷移。如果一個數據塊可以INSERT,當插入一個當前塊裝不下的行時,這個行會溢出到兩個或兩個幾上的塊中,這叫行鏈接。如果用戶的動作是INSERT 則服務器進程會先鎖定FREELIST,然后找到空閑塊的地址,再釋放FREELIST,當多個服務器進程同時想要鎖定FREELIST時即發生FREELIST的爭用,可以在非采用自動段空間管理的表空間中創建表時指定FREELIST的個數,默認為1,如果是在采用自動段空間管理的表空間中創建表,即使指定了FREELIST也會被忽略,因為此時將使用BITMAP而不是FREELIST來管理段中的空閑空間。如果用戶動作是UPDATE服務器進程將不會使用到FREELIST和BITMAP,因為不要去尋找一個空閑塊,而使用鎖的隊列。

              下面來講一下ORACLE鎖的機制,ORACLE分鎖存器和鎖兩種。鎖存器是用來保護對內存結構的訪問,比如對DB BUFFER中塊的鎖存器申請,只有在DBWN完成后,這些DB BUFFER塊被解鎖。然后用于其它的申請。鎖存器不可以在進程間共享,鎖存器的申請要么成功要么失敗,沒有鎖存器申請隊列。主要的鎖存器有SHARED POOL鎖存器,LIBRARY CACHE鎖存器,CACHE BUFFERS LRU CHAIN鎖存器,CACHE BUFFERS CHAINS 鎖存器,REDO ALLOCATION 鎖存器,REDO COPY 鎖存器。ORACLE的鎖是用來保護數據訪問的,鎖的限制比鎖存器要更寬松,比如,多個用戶在修改同一表的不同行時,可以共享一個表上的一個鎖,鎖的申請可以按照被申請的順序來排隊等候,然后依次應用,這種排隊機制叫做隊列(ENPUEUE),如果兩個服務器進程試圖對同一表的同一行進行加鎖,則都進入鎖的申請隊列,先進的加鎖成功,后面的進程要等待,直到前一個進程解鎖才可以加鎖,這叫做鎖的爭用,而且一旦加鎖成功,這個鎖將一直保持到用戶發出COMMIT或ROOLBACK命令為止。如果兩個用戶鎖定各自的一行并請求對方鎖定的行的時候將發生無限期等待即死鎖,死鎖的發生都是由于鎖的爭用而不是鎖存器的爭用引起的,ORACLE在遇到死鎖時,自動釋放其中一個用戶的鎖并回滾此用戶的改變。正常情況下發生鎖的爭用時,數據的最終保存結果由SCN來決定哪個進程的更改被最終保存。兩個用戶的服務器進程在申請同一表的多個行的鎖的時候是可以交錯進入鎖的申請隊列的。只有其中發生爭用才會進行等待。創建表時指定的MAXTRANS參數決了,表中的一個數據塊最多可以被幾個事務同時鎖定。

              下面是幾個關于回滾段和死鎖的事例:

              有表:Test (id number(10)) 有記錄1000000條

          一,大SELECT,小UPDATE
              A會話----Select * from test;----設scn=101----執行時間09:10:11
              B會話-----Update test set id=9999999 where id=1000000----設scn=102-----執行時間09:10:12

              我們會發現B會話會在A會話前完成,A會話中顯示的ID=100000是從回滾段中讀取的,因為A會話在讀到ID=1000000所在的BLOCK時發現BLOCK上有事務信息,因此要從回滾段中讀,如果UPDATE在SELECT讀到此BLOCK之前已經COMMIT,則SELECT 讀到此BLOCK時發現其BLOCK上沒有事務信息,但是會發現其BLICK的SCN比SELECT自己的SCN大,因此也會從回滾段中讀取。因此是否從回滾段讀一是看是否有事務信息二是比較SCN大小。如果B會話在A會話結束前連續多次對同一條記錄UPDATE并COMMIT,那么在回滾段中將記錄多個“前映像”,而每個“前映像”中不但包括了原BLOCK的數據和SCN也記錄了“前前映像”的回滾段地址,因此A會話在查詢到被UPDATE過的BLOCK時,會根據BLOCK記錄的回滾段的地址,找到回滾段中的“前映像”,發現這個“前映像”的SCN也比自己的大,因此將根據這個“前映像”中記錄的“前前映像”的回滾段地址,在回滾段中找到“前前映像”,再與這個“前前映像”比較SCN,如果比自己小就讀取,如果還比自己大,則重復以上步驟,直到找到比自己SCN小的“前…前映像”為止,如果找不到,就會報ORA-01555快照太舊這個錯誤。

          二、大UPDATE,小SELECT

              A會話----Update test set id=1;----設scn=101----執行時間09:10:11
              B會話-----select * from test where id=1000000----設scn=102-----執行時間09:10:12

              我們會發現B會話會在A會話前完成,B會話中顯示的ID=1000000是從BLOCK中直接讀取的,因為B會話在讀到ID=1000000所在的BLOCK時,A會話還沒有來得及對其鎖定,因此B會話既不會發現BLOCK上有事務信息,也不會發現BLOCK上的SCN比SELECT的大,因此會從BLOCK中直接讀取,如果SELECT在UPDATE鎖定此BLOCK后才發出,B會話讀到此BLOCK時發現其BLOCK上有事務信息,因此會從回滾段中讀取。

          三、大UPDATE,小UPDATE

              A會話----Update test set id=1;----設scn=101----執行時間09:10:11
              B會話1-----Update test set id=999999 where id=1000000----設scn=102-----執行時間09:10:12 
              B會話2----- select * from test where id=2----設scn=103-----執行時間09:10:14 
              B會話3----- update test set id=3 where id=2----設scn=104-----執行時間09:10:15

              我們會發現B會話1會完成,A會話將一直等待,因為B會話1會先于A會話鎖定ID=1000000所在的BLOCK,并改寫頭部的事務信息,A會話在試圖鎖定此BLOCK時,發現其上有事務信息,將會一直等待B會話1事務結束后再行鎖定, B會話2查詢到的ID=2是從回滾段中讀取的而不是從BLOCK中直接讀出來的。因為A會話已將ID=2的BLOCK鎖定,并寫入了回滾段,從B會話3可以證明這一點,B會話3發出后,B會話3會收到死鎖的信息,死鎖的原因是A會話在等待B會話對ID=1000000所在的BLOCK解鎖,現在B會話又在等待A會話對ID=2所在的BLOCK解鎖,因此形成死鎖,因此證明ID=2所在的BLOCK已被A會話鎖定,然后A會話也會收到死鎖的信息

          posted @ 2010-06-28 10:42 xzc 閱讀(173) | 評論 (0)編輯 收藏
          #文件行數
          file_count=`wc -l /odsstatfs/groupfile/${file_name} | awk '{print $1}'`
          echo "文件行數:${file_count}"
          #文件大小
          file_size=`ls -l /odsstatfs/groupfile/${file_name} | awk '{print $5}'`
          echo "文件大小:${file_size}"


          總結了一下有五種方法:

            現在有一個a文件,共有55行

            第一種:

            # awk '{print NR}' a|tail -n1

            55

            第二種:

            begincwcw兄的這個:

            # awk 'END{print NR}' a

            55

            第三種:

            # grep -n "" a|awk -F: '{print '}|tail -n1

            55

            第四種:

            honbj兄的也不錯:

            # sed -n '$=' a

            55

            第五種

            # wc -l a|awk '{print }'

            55

            第六種

            #cat a |wc -l

            55


          文件內容統計命令:wc
          http://www.fanqiang.com (2001-05-08 14:24:15)
          wc命令的功能為統計指定文件中的字節數、字數、行數, 并將統計結果顯示輸出。 

          語法:wc [選項] 文件… 

          說明:該命令統計給定文件中的字節數、字數、行數。如果沒有給出文件名,則從標準輸入讀取。wc同時也給出所有指定文件的總統計數。字是由空格字符區分開的最大字符串。 

          該命令各選項含義如下: 

          - c 統計字節數。 

          - l 統計行數。 

          - w 統計字數。 

          這些選項可以組合使用。 

          輸出列的順序和數目不受選項的順序和數目的影響。總是按下述順序顯示并且每項最多一列。 

          行數、字數、字節數、文件名 

          如果命令行中沒有文件名,則輸出中不出現文件名。 

          例如: 

          $ wc - lcw file1 file2 

          4 33 file1 

          7 52 file2 

          11 11 85 total 

          省略任選項-lcw,wc命令的執行結果與上面一樣。 
          posted @ 2010-04-22 14:56 xzc 閱讀(4057) | 評論 (0)編輯 收藏

          一、特殊符號ascii定義
           制表符 chr(9)
           換行符 chr(10)
           回車符 chr(13)

          二、嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行
                    select REPLACE(gg, chr(10), '') from dual
              要注意chr(13) | | chr(10) 此類結合使用的情況比較多,回車換行在notepad中是比較好看點的,所以要考慮此種情況
                    select translate(string,chr(13)||chr(10),',') from dual;
          1、例子一
          create table TEST_1
          (
            VA  VARCHAR2(10),
            VB  NUMBER(2),
            VC  VARCHAR2(10),
            VD  NUMBER(11,2),
            VE  NUMBER(11,4),
            VCL CLOB
          );

          SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(10),',') from test_1;
           
           VB VC         TT         TRANSLATE(VC,CHR(10),',')
          --- ---------- ---------- -------------------------
            0 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
            1 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
            2 大Ba       大Babc帶   大Ba,b,c帶
              b                    
              c帶                  
           
            3 C          C          C
            1 D          D          D
            5 A          A          A
            5 A          A          A
            0 A          A          A
            0 A          A          A
           
           2、例子二
          要注意chr(13) | | chr(10) 此類結合使用的情況比較多,回車換行在notepad中是比較好看點的,所以要考慮此種情況
          select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
          SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
           
           VB VC         TT         TRANSLATE(VC,CHR(13)||CHR(10),
          --- ---------- ---------- ------------------------------
            0 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
            1 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
            2 大Ba       大Babc帶   大Babc帶
              b                    
              c帶                  
           
            3 C          C          C
            1 D          D          D
            5 A          A          A
            5 A          A          A
            0 A          A          A
            0 A          A          A
           
          11 rows selected

          三、對于字符大對象的符號處理
              對于clob字段中的符號處理,先to_char然后一樣的處理

          SQL> select to_char(vcl),replace(to_char(vcl),chr(10),'[]') from test_1;
           
          TO_CHAR(VCL)                                                                     REPLACE(TO_CHAR(VCL),CHR(10),'
          -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
          嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行                        嵌套使用repalce,注意每次只能提交一個符號,如先回車再換行[]select REPLACE(gg, chr(10), '') from dual[]sel
          select REPLACE(gg, chr(10), '') from dual                                       
          select translate(string,chr(13)||chr(10),',') from dual;    

          func:

           

          2.2.1      單記錄字符函數

                  函     數                      說                明
            ASCII                     返回對應字符的十進制值
            CHR                       給出十進制返回字符 
           CONCAT                    拼接兩個字符串,與  ||       相同
            INITCAT                   將字符串的第一個字母變為大寫
            INSTR                     找出某個字符串的位置
            INSTRB                    找出某個字符串的位置和字節數
            LENGTH                    以字符給出字符串的長度
            LENGTHB                   以字節給出字符串的長度
            LOWER                     將字符串轉換成小寫
            LPAD                      使用指定的字符在字符的左邊填充
            LTRIM                     在左邊裁剪掉指定的字符
            RPAD                      使用指定的字符在字符的右邊填充
            RTRIM                     在右邊裁剪掉指定的字符
            REPLACE                   執行字符串搜索和替換
            SUBSTR                    取字符串的子串
            SUBSTRB                   取字符串的子串(以字節)
            SOUNDEX                   返回一個同音字符串
            TRANSLATE                 執行字符串搜索和替換
            TRIM                      裁剪掉前面或后面的字符串
            UPPER                     將字符串變為大寫
            NVL                       以一個值來替換空值

          ASCII(<c1>)
          <c1>是字符串。返回與指定的字符對應的十進制數。
          SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual;

               A      a  ZERO   SPACE
          ---------- ---------- ---------- ----------
               65     97     48     32

          SQL> select ascii('趙') zhao,length('趙') leng from dual;

                ZHAO        LENG
              ----------  ----------
               54740         1

          CHR(<I>[NCHAR])
          給出整數,返回對應字符。如:

          SQL> select chr(54740) zhao,chr(65) chr65 from dual;

          ZH   C
          --  -
          趙  A

          CONCAT(<c1>,<c2>)
          SQL> select concat('010-','8801 8159')||'轉23' 趙元杰電話  from dual;

          趙元杰電話

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

          010-8801 8159 轉23

          INITCAP(<c1>)

          返回字符串c1       并第一個字母變為大寫。例如:

          SQL> select initcap('simth') upp from dual;

          UPP
          -----
          Simth

          INSTR(<c1>,<c2>[,<I>[,<j>] ] )
          在一個字符串中搜索指定的字符,返回發現指定的字符的位置。
          C1: 被搜索的字符串 
          C2: 希望搜索的字符串 
          I: 搜索的開始位置,缺省是1 
          J: 出現的位置,缺省是1。 

          SQL> SELECT INSTR ('Oracle Training', 'ra', 1, 2) "Instring" FROM DUAL;

            Instring

          ----------

                  9

          INSTRB(<c1>,<c2>[,<I>[,<j>] ] )

          除了返回的字節外 ,與INSTR              相同,

          LENGTH( <c> )

          返回字符串  c      的長度。

          SQL> l
           1  select name,length(name),addr,length(addr),sal,length(to_char(sal))
            2* from nchar_tst
          SQL> /

          NAME    LENGTH(NAME) ADDR            LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL))

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

          趙元杰          3        北京市海淀區                 6         99999.99    8

          LENGTHB( <c> )

          以字節返回字符串的字節數。

          SQL> select name,lengthb(name),length(name) from nchar_tst;

          NAME     LENGTHB(NAME)       LENGTH(NAME)

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

          趙元杰                 6             3

          LOWER ( <c> )
          返回字符串并將所有字符變為小寫。

          SQL> select lower('AaBbCcDd') AaBbCcDd from dual;

          AABBCCDD

          --------

          aabbccdd

          UPPER( <c>)
          與  LOWER    相反,將給出字符串變為大寫。如:

          SQL>    select upper('AaBbCcDd') AaBbCcDd from dual;

          AABBCCDD

          --------

          AABBCCDD
          RPAD 和LPAD(粘貼字符)
           
          RPAD(string,Length[,'set']) 
          LPAD(string,Length[,'set']) 
                RPAD在列的右邊粘貼字符; 
                LPAD在列的左邊粘貼字符。 
           
          例 1: 
          SQL>select   RPAD(City,35,'.'),temperature    from  weather; 
           
                  RPAD(City,35,'.')            temperature 
                  -------------------------- ---------------- 
                     CLEVELAND......                    85 
                     LOS  ANGELES..                     81 
                    ......................... 
           
                  (即不夠 35 個字符用'.'填滿) 

          LTRIM(左截斷)RTRIM(右截斷) 函數 
           

          LTRIM (string [,’set’])

          Left TRIM (左截斷)刪去左邊出現的任何set 字符。 

          RTRIM (string [,’set’])

          Right TRIM (右截斷)刪去右邊出現的任何set 字符。 

          例1: 

          SELECT RTRIM (‘Mother Theresa, The’, ‘The’) “Example of Right

          Trimming” FROM DUAL;

          Example of Right

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

          Mother Theresa,

          SUBSTR Substr(string,start[,Count])

          取子字符串中函數 
          對字串 (或字段),從 start字符 開始,連續取 count 個字符并返回結果,如果沒有指 count
          則一直取到尾。 
           
          select phone,substr(phone,1,3) || ‘0’ || substr(phone,4) 
          from telecommunication where master ’中國電信’; 
           

          SUBSTRB(string,start[,Count])
          對字串 (或字段),從 start字節 開始,連續取 count 個字節并返回結果,如果沒有指 count
          則一直取到尾。 
           
           
          REPLACE (‘string’ [,’string_in’,’string_out’])

          String: 希望被替換的字符串或變量。 
          String_in: 被替換字符串。 
          String_out: 要替換字符串。 
           
          SQL> select replace('Informaix 中國公司','Informaix','IBM Informix')
            2  IBM 數據庫  from dual;

          IBM 數據庫
          --------------------
          IBM Informix 中國公司

          SOUNDEX( <c> )

          返回一個與給定的字符串讀音相同的字符串(不管拼寫是否一樣)。

          SELECT DPL_NAME FROM DENIED_PARTIES_LIST WHERE
          SOUNDEX(DPL_NAME) = SOUNDEX(‘Saddam Hussain’) ;
          DPL_NAME
          ----------------------------------------------
          Al Husseni
          Sadda Al Sada.

          REPLACE (‘string’ [,’string_in’,’string_out’])

          String:希望被替換的字符串或變量。 
          String_in: 被替換字符串。 
          String_out: 要替換字符串。 
           
          SELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL; 
          Example 
          ------- 
          Miracle 

          TRIM  ( [<leading>] <trailing> FROM <trim_char>     )
          RIM可以使你對給定的字符串進行裁剪(前面,后面或前后)。 

          z 如果指定 LEADING, Oracle 從trim_char 中裁剪掉前面的字符; 
          z 如果指定TRAILING, Oracle 從trim_char 中裁剪掉尾面的字符; 
          z 如果指定兩個都指定或一個都沒有給出,Oracle從trim_char 中裁剪掉前面及尾面的字
             符; 
          z 如果不指定 trim_character, 缺省為空格符; 
          z 如果只指定trim_source, Oracle Oracle從trim_char 中裁剪掉前面及尾面的字符。 
           
          例子:將下面字符串中的前面和后面的‘0                   ‘字符都去掉:

          SELECT TRIM (0 FROM 0009872348900) "TRIM Example" FROM DUAL;

          TRIM example

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

          98723489

           

          語法:TRANSLATE(expr,from,to)

          om,to) expr: 代表一串字符,

          expr: 代表一串字符,from 與 to 是從左到右一一對應的關系,如果不能對應,則視為空值。

          舉例:

          select translate('abcbbaadef','ba','#@') from dual (b將被#替代,a將被@替代)

          select translate(ab

          select translate('abcbbaadef','bad','#@') from dual (b將被#替代,a將被@替代,d對應的值是空值,將被移走)

          因此:結果依次為:@#c##@@def 和@#c##@@ef

          posted @ 2010-04-22 11:10 xzc 閱讀(10678) | 評論 (0)編輯 收藏

          一個大型文件(總之不小),要求刪除該文件的最后一行,求一種效率比較高的解決方法。

          測試用的文本文件800M
          1.用sed解決,此法最易想,但也是最笨的一個,
          解決方法來自問題的提出者:
          sed -e '$d' input.file > output.file
          用time測試了一下,效率是相當的低!
          real    2m51.099s
          user    2m1.268s
          sys    0m4.260s
          2.用head解決,此法比sed有一個質的的提升,提升來自增大了緩存,不過依然沒有抓住問題的本質,還是做了不少無用功!解決方法來時cu上的熱心網友。
          head -n-1 input.file > output.file
          real    0m23.687s
          user    0m0.212s
          sys    0m4.668s
          3.用vim解決,此法很別處心裁,這應該是遇到這個問題的最先想到的一種。解決方法來自我加的unix like群里的一個叫石仔的管理員!
          vim + result
          dd
          這個沒測試,感覺效率和head法差不多,加載太慢!
          4.重量級要到場了,感謝cu版主的這個腳本,只能用四個字形容!五體投地!
          :|dd of=input.file seek=1 bs=$(($(find input.file -printf "%s")-$(tail -1 input.file|wc -c)))
          或者是
          :|dd of=input.file seek=1 bs=$(($(stat -c%s input.file)-$(tail -1 input.file|wc -c)))
          測試了一下!
          real    0m0.123s
          user    0m0.004s
          sys    0m0.012s
          5.感覺這個用c寫效率最高,但顯然,代碼也是最長的,我實現了代碼,
          測試了一下,
          real    0m0.002s
          user    0m0.000s
          sys    0m0.000s
          代碼如下:

          #include <stdio.h>
          #include <unistd.h>
          #include <fcntl.h>
          #include <sys/stat.h>
          #include <stdlib.h>

          #define GUESS_LINE_SIZE 80
          int get_line_size(char *ptr);

          int
          main(int argc, char *argv[])
          {
              char buf[GUESS_LINE_SIZE];
              int line_len, fd;
              struct stat stat_buf;
             
              fd = open(argv[1], O_RDWR);
              lstat(argv[1], &stat_buf);
              lseek(fd, -GUESS_LINE_SIZE, SEEK_END);
              read(fd, buf, GUESS_LINE_SIZE) ;
              line_len = get_line_size(buf);
              truncate(argv[1], stat_buf.st_size - line_len);
             
              exit(0);
          }

          int
          get_line_size(char *ptr)
          {
              int line_len = 0, i = GUESS_LINE_SIZE - 2;/*buf中的最后一個字符為'\n'*/
             
              while (*(ptr + i) != '\n') {
                  //printf("%c", *(ptr + i));

                  i--;
                  line_len++;
              }
              return line_len;
          }

          posted @ 2010-04-21 18:45 xzc 閱讀(3294) | 評論 (2)編輯 收藏

          在linux下獲取時間字符串
          命令 date
          # 以yyyymmdd格式輸出23天之前現在這個時刻的時間
          $ date +%Y%m%d –date=’23 days ago’

          $ date -u
          Thu Sep 28 09:32:04 UTC 2006

          $ date -R
          Thu, 28 Sep 2006 17:32:28 +0800

          # 測試十億分之一秒
          $ date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’
          20060928 17:44:20.906805000
          20060928 17:44:20.909188000
          20060928 17:44:20.911535000
          20060928 17:44:20.913886000
          date 參考
          $ date –help
          Usage: date [OPTION]… [+FORMAT]
          or: date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
          Display the current time in the given FORMAT, or set the system date.

          -d, –date=STRING display time described by STRING, not `now’
          # such as ‘n days ago |1 month ago|n years ago’
          -f, –file=DATEFILE like –date once for each line of DATEFILE
          -ITIMESPEC, –iso-8601[=TIMESPEC] output date/time in ISO 8601 format.
          TIMESPEC=`date’ for date only,
          `hours’, `minutes’, or `seconds’ for date and
          time to the indicated precision.
          –iso-8601 without TIMESPEC defaults to `date’.
          -r, –reference=FILE display the last modification time of FILE
          -R, –rfc-2822 output RFC-2822 compliant date string
          -s, –set=STRING set time described by STRING
          -u, –utc, –universal print or set Coordinated Universal Time
          –help display this help and exit
          –version output version information and exit

          FORMAT controls the output. The only valid option for the second form
          specifies Coordinated Universal Time. Interpreted sequences are:

          %% 輸出%符號 a literal %
          %a 當前域的星期縮寫 locale’s abbreviated weekday name (Sun..Sat)
          %A 當前域的星期全寫 locale’s full weekday name, variable length (Sunday..Saturday)
          %b 當前域的月份縮寫 locale’s abbreviated month name (Jan..Dec)
          %B 當前域的月份全稱 locale’s full month name, variable length (January..December)
          %c 當前域的默認時間格式 locale’s date and time (Sat Nov 04 12:02:33 EST 1989)
          %C n百年 century (year divided by 100 and truncated to an integer) [00-99]
          %d 兩位的天 day of month (01..31)
          %D 短時間格式 date (mm/dd/yy)
          %e 短格式天 day of month, blank padded ( 1..31)
          %F 文件時間格式 same as %Y-%m-%d
          %g the 2-digit year corresponding to the %V week number
          %G the 4-digit year corresponding to the %V week number
          %h same as %b
          %H 24小時制的小時 hour (00..23)
          %I 12小時制的小時 hour (01..12)
          %j 一年中的第幾天 day of year (001..366)
          %k 短格式24小時制的小時 hour ( 0..23)
          %l 短格式12小時制的小時 hour ( 1..12)
          %m 雙位月份 month (01..12)
          %M 雙位分鐘 minute (00..59)
          %n 換行 a newline
          %N 十億分之一秒 nanoseconds (000000000..999999999)
          %p 大寫的當前域的上下午指示 locale’s upper case AM or PM indicator (blank in many locales)
          %P 小寫的當前域的上下午指示 locale’s lower case am or pm indicator (blank in many locales)
          %r 12小時制的時間表示(時:分:秒,雙位) time, 12-hour (hh:mm:ss [AP]M)
          %R 24小時制的時間表示 (時:分,雙位)time, 24-hour (hh:mm)
          %s 自基礎時間 1970-01-01 00:00:00 到當前時刻的秒數 seconds since `00:00:00 1970-01-01 UTC’ (a GNU extension)
          %S 雙位秒 second (00..60); the 60 is necessary to accommodate a leap second
          %t 橫向制表位(tab) a horizontal tab
          %T 24小時制時間表示 time, 24-hour (hh:mm:ss)
          %u 數字表示的星期(從星期一開始 1-7)day of week (1..7); 1 represents Monday
          %U 一年中的第幾周星期天為開始 week number of year with Sunday as first day of week (00..53)
          %V 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (01..53)
          %w 一周中的第幾天 星期天為開始 0-6 day of week (0..6); 0 represents Sunday
          %W 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (00..53)
          %x 本地日期格式 locale’s date representation (mm/dd/yy)
          %X 本地時間格式 locale’s time representation (%H:%M:%S)
          %y 兩位的年 last two digits of year (00..99)
          %Y 年 year (1970…)
          %z RFC-2822 標準時間格式表示的域 RFC-2822 style numeric timezone (-0500) (a nonstandard extension)
          %Z 時間域 time zone (e.g., EDT), or nothing if no time zone is determinable

          By default, date pads numeric fields with zeroes. GNU date recognizes
          the following modifiers between `%’ and a numeric directive.

          `-’ (hyphen) do not pad the field
          `_’ (underscore) pad the field with spaces

          posted @ 2010-04-20 10:55 xzc 閱讀(6962) | 評論 (1)編輯 收藏
          oracle table-lock的5種模式

          Oracle中的鎖定可以分為幾類:
          1、DML lock(data lock),
          2、DDL lock(dictionary lock)
          3、internal lock/latch。

          DML lock又可以分為row lock和table lock。row lock在select.. for update/insert/update/delete時隱式自動產生,而table lock除了隱式產生,也可以調用lock table <table_name> in </table_name> name來顯示鎖定。

          如果不希望別的session lock/insert/update/delete表中任意一行,只允許查詢,可以用lock table table_name in exclusive mode。(X)這個鎖定模式級別最高,并發度最小。

          如果允許別的session查詢或用select for update鎖定記錄,不允許insert/update/delete,可以用
          lock table table_name in share row exclusive mode。(SRX)

          如果允許別的session查詢或select for update以及lock table table_name in share mode,只是不允許insert/update/delete,可以用
          lock table table_name in share mode。(share mode和share row exclusive mode的區別在于一個是非搶占式的而另一個是搶占式的。進入share row exclusive mode后其他session不能阻止你insert/update/delete,而進入share mode后其他session也同樣可以進入share mode,進而阻止你對表的修改。(S)

          還有兩種鎖定模式,row share(RS)和row exclusive(RX)。他們允許的并發操作更多,一般直接用DML語句自動獲得,而不用lock語句。
          詳細參考concepts文檔中的"Type Of Locks":
          http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96524/c21cnsis.htm#2937


          -------------------------------------
          怎么unlock table 解鎖

          方法一、kill session:

          SQL> select object_id,session_id from v$locked_object;  //注意session_id 就是上鎖的 session標志
          SQL> select username,sid,SERIAL#  from v$session where sid=。。;      //這里的SID = session_id
          SQL> alter system kill session 'id,serial#';     //殺死該session

          方法二、rollback/commit 終止事務處理
          posted @ 2010-04-02 16:05 xzc 閱讀(7240) | 評論 (1)編輯 收藏

          二元比較操作符,比較變量或者比較數字.注意數字與字符串的區別.
           
          整數比較
           
          -eq        等于,如:if [ "$a" -eq "$b" ]
          -ne        不等于,如:if [ "$a" -ne "$b" ]
          -gt        大于,如:if [ "$a" -gt "$b" ]
          -ge        大于等于,如:if [ "$a" -ge "$b" ]
          -lt        小于,如:if [ "$a" -lt "$b" ]
          -le        小于等于,如:if [ "$a" -le "$b" ]
          <        小于(需要雙括號),如:(("$a" < "$b"))
          <=        小于等于(需要雙括號),如:(("$a" <= "$b"))
          >        大于(需要雙括號),如:(("$a" > "$b"))
          >=        大于等于(需要雙括號),如:(("$a" >= "$b"))
           
          字符串比較
          =        等于,如:if [ "$a" = "$b" ]
          ==        等于,如:if [ "$a" == "$b" ],與=等價
                  注意:==的功能在[[]]和[]中的行為是不同的,如下:
                  1 [[ $a == z* ]]    # 如果$a以"z"開頭(模式匹配)那么將為true
                  2 [[ $a == "z*" ]]  # 如果$a等于z*(字符匹配),那么結果為true
                  3 
                  4 [ $a == z* ]      # File globbing 和word splitting將會發生
                  5 [ "$a" == "z*" ]  # 如果$a等于z*(字符匹配),那么結果為true
                  一點解釋,關于File globbing是一種關于文件的速記法,比如"*.c"就是,再如~也是.
                  但是file globbing并不是嚴格的正則表達式,雖然絕大多數情況下結構比較像.
          !=        不等于,如:if [ "$a" != "$b" ]
                  這個操作符將在[[]]結構中使用模式匹配.
          <        小于,在ASCII字母順序下.如:
                  if [[ "$a" < "$b" ]]
                  if [ "$a" \< "$b" ]
                  注意:在[]結構中"<"需要被轉義.
          >        大于,在ASCII字母順序下.如:
                  if [[ "$a" > "$b" ]]
                  if [ "$a" \> "$b" ]
                  注意:在[]結構中">"需要被轉義.
                  具體參考Example 26-11來查看這個操作符應用的例子.
          -z        字符串為"null".就是長度為0.
          -n        字符串不為"null"
                  注意:
                  使用-n在[]結構中測試必須要用""把變量引起來.使用一個未被""的字符串來使用! -z
                  或者就是未用""引用的字符串本身,放到[]結構中。雖然一般情況下可
                  以工作,但這是不安全的.習慣于使用""來測試字符串是一種好習慣.

          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhrmghl/archive/2006/10/22/1345115.aspx

          posted @ 2010-04-02 14:17 xzc 閱讀(1193) | 評論 (0)編輯 收藏
          測試平臺:RHEL4.5

          一、最簡單的shell里調用sqlplus.


          $ vi test1.sh

          #!/bin/bash
          sqlplus -S /nolog > result.log <<EOF
          set heading off feedback off pagesize 0 verify off echo off
          conn u_test/iamwangnc
          select * from tab;
          exit
          EOF

          $ chmod +x test1.sh
          $ ./test1.sh

          二、把sqlplus執行結果傳遞給shell方法一

          注意sqlplus段使用老板鍵`了, 賦變量的等號兩側不能有空格.

          $ vi test2.sh

          #!/bin/bash
          VALUE=`sqlplus -S /nolog <<EOF
          set heading off feedback off pagesize 0 verify off echo off numwidth 4
          conn u_test/iamwangnc
          select count(*) from tab;
          exit
          EOF`
          if [ "$VALUE" -gt 0 ]; then
                  echo "The number of rows is $VALUE."
                  exit 0
          else
                  echo "There is no row in the table."
          fi

          $ chmod +x test2.sh
          $ ./test2.sh

          三、把sqlplus執行結果傳遞給shell方法二

          注意sqlplus段使用 col .. new_value .. 定義了變量并帶參數exit, 然后自動賦給了shell的$?

          $ vi test3.sh

          #!/bin/bash
          sqlplus -S /nolog > result.log <<EOF
          set heading off feedback off pagesize 0 verify off echo off numwidth 4
          conn u_test/iamwangnc
          col coun new_value v_coun
          select count(*) coun from tab;
          exit v_coun
          EOF
          VALUE="$?"
          echo "The number of rows is $VALUE."

          $ chmod +x test3.sh
          $ ./test3.sh

          四、把shell程序參數傳遞給sqlplus

          $1表示第一個參數, sqlplus里可以直接使用, 賦變量的等號兩側不能有空格不能有空格.

          $ vi test4.sh

          #!/bin/bash
          NAME="$1"
          sqlplus -S u_test/iamwangnc <<EOF
          select * from tab where tname = upper('$NAME');
          exit
          EOF

          $ chmod +x test4.sh
          $ ./test4.sh ttt

          五、為了安全要求每次執行shell都手工輸入密碼

          $ vi test5.sh

          #!/bin/bash
          echo -n "Enter password for u_test:"
          read PASSWD
          sqlplus -S /nolog <<EOF
          conn u_test/$PASSWD
          select * from tab;
          exit
          EOF

          $ chmod +x test5.sh
          $ ./test5.sh

          六、為了安全從文件讀取密碼

          對密碼文件設置權限, 只有用戶自己才能讀寫.

          $ echo 'iamwangnc' > u_test.txt
          $ chmod g-rwx,o-rwx u_test.txt
          $ vi test6.sh

          #!/bin/bash
          PASSWD=`cat u_test.txt`
          sqlplus -S /nolog <<EOF
          conn u_test/$PASSWD
          select * from tab;
          exit
          EOF

          $ chmod +x test6.sh
          $ ./test6.sh

          --End--
          posted @ 2010-04-01 12:05 xzc 閱讀(4795) | 評論 (0)編輯 收藏
          原文鏈接:http://bbs.linuxtone.org/thread-5317-1-1.html IT運維專家網--"自由平等,互助分享!"
          shell中數組的下標默認是從0開始的

          1. 將字符串存放在數組中,獲取其長度
          #!/bin/bash
          str="a b --n d"
          array=($str)
          length=${#array[@]}
          echo $length

          for ((i=0; i<$length; i++))
          do
              echo ${array[$i]}
          done
          along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
          4
          a
          b
          --n
          d

          打印字符串:
          [root@mc2 tmp]# cat test.sh
          #!/bin/bash
          str="a b c"
          for i in $str
          do
          echo $i
          done

          [root@mc2 tmp]# cat array.sh
          #!/bin/bash
          str="a b c"
          array=($str)
          for ((i=0;i<${#array[@]};i++))
          do
            echo ${array[$i]}
          done

          結果:
          a
          b
          c

          2. 字符串用其他字符分隔時
          #!/bin/bash

          str2="a#b#c"
          a=($(echo $str2 | tr '#' ' ' | tr -s ' '))
          length=${#a[@]}

          for ((i=0; i<$length; i++))
          do
              echo ${a[$i]}
          done
          #echo ${a[2]}

          along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
          a
          b
          c

          3. 數組的其他操作
          #!/bin/bash
          str="a b --n dd"
          array=($str)
          length=${#array[@]}

          #直接輸出的是數組的第一個元素
          echo $array

          #用下標的方式訪問數組元素
          echo ${array[1]}

          #輸出這個數組
          echo ${array[@]}

          #輸出數組中下標為3的元素的長度
          echo ${#array[3]}

          #輸出數組中下標為1到3的元素
          echo ${array[@]:1:3}

          #輸出數組中下標大于2的元素
          echo ${array[@]:2}

          #輸出數組中下標小于2的元素
          echo ${array[@]::2}

          along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
          a
          b
          a b --n dd
          2
          b --n dd
          --n dd
          a b

          4. 遍歷訪問一個字符串(默認是以空格分開的,當字符串是由其他字符分隔時可以參考 2)
          #!/bin/bash
          str="a --m"
          for i in $str
          do
              echo $i
          done
          along@along-laptop:~/code/shell/shell/mycat/testfile$ ./para_test.sh
          a
          --m

          5. 如何用echo輸出一個 字符串str="-n". 由于-n是echo的一個參數,所以一般的方法echo "$str"是無法輸出的.
          解決方法可以有:

          echo x$str | sed 's/^x//'
          echo -ne "$str\n"
          echo -e "$str\n\c"
          printf "%s\n" $str  (這樣也可以)
          posted @ 2010-03-31 15:28 xzc 閱讀(2988) | 評論 (1)編輯 收藏

          來源地址: http://hi.bccn.net/space-21499-do-blog-id-13524.html

          shell for 循環指令使用
          2008-11-02 22:34

          for可以使一些不支持通配符的命令對一系列文件進行操作。在WIN9X中,TYPE命令(顯示文件內容)是不支持*.txt這種格式的(WIN2K開始TYPE已支持通配)。遇到類似情況就可以用FOR:

              for %a in (*.txt) do type %a

          這些還不是FOR最強大的功能。我認為它最強大的功能,表現在以下這些高級應用:
          1. 可以用 /r 參數遍歷整個目錄樹
          2. 可以用 /f 參數將文本文件內容作為循環范圍
          3. 可以用 /f 參數將某一命令執行結果作為循環范圍
          4. 可以用 %~ 操作符將文件名分離成文件名、擴展名、盤符等獨立部分

           

          現分別舉例說明如下:
          1. 用 /r 遍歷目錄樹
          當用 *.* 或 *.txt 等文件名通配符作為 for /r 的循環范圍時,可以對當前目錄下所有文件(包括子目錄里面的文件)進行操作。舉個例子,你想在當前目錄的所有txt文件(包括子目錄)內容中查找"bluebear"字樣,但由于find本身不能遍歷子目錄,所以我們用for:

              for /r . %a in (*.txt) do @find "bluebear" %a

          find 前面的 @ 只是讓輸出結果不包括 find 命令本身。這是DOS很早就有的功能。和FOR無關。
          當用 . 作為循環范圍時,for 只將子目錄的結構(目錄名)作為循環范圍,而不包括里面的文件。有點象 TREE 命令,不過側重點不同。TREE 的重點是用很漂亮易讀的格式輸出,而FOR的輸出適合一些自動任務,例如,我們都知道用CVS管理的項目中,每個子目錄下都會有一個CVS目錄,有時在軟件發行時我們想把這些CVS目錄全部去掉:
              for /r . %a in (.) do @if exist %aCVS rd /s /q %aCVS

          先用 if exist 判斷一下,是因為 for 只是機械的對每個目錄進行列舉,如果有些目錄下面沒有CVS也會被執行到。用 if exist 判斷一下比較安全。
          這種刪除命令威力太大,請小心使用。最好是在真正執行以上的刪除命令前,將 rd /s /q 換成 @echo 先列出要刪出的目錄,確認無誤后再換回rd /s /q:
              for /r . %a in (.) do @if exist %aCVS @echo %aCVS

          可能目錄中會多出一層 ".",比如 c:proj elease.CVS ,但不會影響命令的執行效果。
          2. 將某一文件內容或命令執行結果作為循環范圍:
          假如你有一個文件 todel.txt,里面是所有要刪除的文件列表,現在你想將里面列出的每個文件都刪掉。假設這個文件是每個文件名占一行,象這樣:
              c: empa1.txt
              c: empa2.txt
              c: empsubdir3.txt
              c: empsubdir4.txt

          那么可以用FOR來完成:
              for /f %a in (todel.txt) do del %a

          這個命令還可以更強大。比如你的 todel.txt 并不是象上面例子那么干凈,而是由DIR直接生成,有一些沒用的信息,比如這樣:
              Volume in drive D is DATA
              Volume Serial Number is C47C-9908
              Directory of D: mp
              09/26/2001 12:50 PM 18,426 alg0925.txt
              12/02/2001 04:29 AM 795 bsample.txt
              04/11/2002 04:18 AM 2,043 invitation.txt
              4 File(s) 25,651 bytes
              0 Dir(s) 4,060,700,672 bytes free

          for 仍然可以解出其中的文件名并進行操作:
              for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a DEL %a

          當然,上面這個命令是在進行刪除,如果你只是想看看哪些文件將被操作,把DEL換成echo:
              for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a echo %a

          你將看到:
              alg0925.txt
              bsample.txt
              invitation.txt

          skip=5表示跳過前5行(就是DIR輸出的頭部信息),tokens=5表示將每行的第5列作為循環值放入%a,正好是文件名。在這里我加了一個文件存在判斷,是因為最后一行的"free"剛好也是第5列,目前還想不出好的辦法來濾掉最后兩行,所以檢查一下可保萬無一失。
          3. 可以用 /f 參數將某一命令執行結果作為循環范圍
          非常有用的功能。比如,我們想知道目前的環境變量有哪些名字(我們只要名字,不要值)。可是SET命令的輸出是“名字=值”的格式,現在可以用FOR來只取得名字部分:
              FOR /F "delims==" %i IN ('set') DO @echo %i

          將看到:
              ALLUSERSPROFILE
              APPDATA
              CLASSPATH
              CommonProgramFiles
              COMPUTERNAME
              ComSpec
              dircmd
              HOMEDRIVE
              ......

          這里是將set命令執行的結果拿來作為循環范圍。delims==表示用=作為分隔符,由于FOR /F默認是用每行第一個TOKEN,所以可以分離出變量名。如果是想僅列出值:
              FOR /F "delims== tokens=2" %i IN ('set') DO @echo %i

          tokens=2和前例相同,表示將第二列(由=作為分隔符)作為循環值。
          再來個更有用的例子:
          我們知道 date /t (/t表示不要詢問用戶輸入)的輸出是象這樣的:
              Sat 07/13/2002

          現在我想分離出日期部分,也就是13:
              for /f "tokens=3 delims=/ " %a in ('date /t') do @echo %a

          實際上把 tokens后面換成1,2,3或4,你將分別得到Sat, 07, 13和2002。注意delims=/后面還有個空格,表示/和空格都是分隔符。由于這個空格delims必須是/f選項的最后一項。
          再靈活一點,象本文開頭提到的,將日期用2002-07-13的格式輸出:
              for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b

          當tokens后跟多個值時,將分別映射到%a, %b, %c等。實際上跟你指定的變量有關,如果你指定的是 %i, 它們就會用%i, %j, %k等。
          靈活應用這一點,幾乎沒有做不了的事。
          4. 可以用 %~ 操作符將文件名分離成文件名、擴展名、盤符等獨立部分
          這個比較簡單,就是說將循環變量的值自動分離成只要文件名,只要擴展名,或只要盤符等等。
          例:要將 c:mp3下所有mp3的歌名列出,如果用一般的 dir /b/s 或 for /r ,將會是這樣:
              g:mp3Archived-18-01-A游鴻明-下沙游鴻明-01 下沙.mp3
              g:mp3Archived-18-01-A游鴻明-下沙游鴻明-02 21個人.mp3
              ......
              g:mp3Archived-18-01-A王菲-寓言王菲-阿修羅.mp3
              g:mp3Archived-18-01-A王菲-寓言王菲-彼岸花.mp3
              g:mp3Archived-18-01-A王菲-寓言王菲-不愛我的我不愛.mp3
              ......

          如果我只要歌名(不要路徑和".mp3"):
              游鴻明-01 下沙
              游鴻明-02 21個人
              ......
              王菲-阿修羅
              王菲-彼岸花
              王菲-不愛我的我不愛
              ......

          那么可以用FOR命令:
              for /r g:mp3 %a in (*.mp3) do @echo %~na

          凡是 %~ 開頭的操作符,都是文件名的分離操作。具體請看 for /? 幫助。
          本文舉的例子有些可能沒有實際用處,或可用其它辦法完成。僅用于體現FOR可以不借助其它工具,僅用DOS命令組合,就可完成相當靈活的任務。
          posted @ 2010-03-31 14:41 xzc 閱讀(3003) | 評論 (0)編輯 收藏
          僅列出標題
          共32頁: First 上一頁 13 14 15 16 17 18 19 20 21 下一頁 Last 
          主站蜘蛛池模板: 桃源县| 阜南县| 抚宁县| 浑源县| 乐昌市| 阳高县| 甘孜县| 张掖市| 南昌县| 宜州市| 鹤庆县| 仙桃市| 武鸣县| 大渡口区| 吉木乃县| 姜堰市| 炎陵县| 南澳县| 长汀县| 巨野县| 泰和县| 临城县| 毕节市| 九台市| 奇台县| 普定县| 寿宁县| 于田县| 佛冈县| 临猗县| 鱼台县| 东宁县| 苍梧县| 紫云| 曲沃县| 大冶市| 类乌齐县| 沙河市| 阜平县| 根河市| 阳泉市|