shell求絕對值及一份不錯的shell資料
轉自:
將目前大家的方法稍微整理了一下,都寫成了函式:
abs () { echo ${1#-};}
abs () { echo $1 | tr -d -;}
abs () { echo $1 | awk '{print sqrt($1*$1)}';}
abs () { echo $1 | sed 's/^-//';}
也許以後大家遇到相同的問題,在不同的情況下能找到最適合的方法。
abs () { echo ${1#-};}
abs () { echo $1 | tr -d -;}
abs () { echo $1 | awk '{print sqrt($1*$1)}';}
abs () { echo $1 | sed 's/^-//';}
也許以後大家遇到相同的問題,在不同的情況下能找到最適合的方法。
另外發現一個不錯的shell文件:
SHELL SCRIPTING 教學與心得
基本觀念與操作
建立第一個shell script
起始檔案 startup files
命令區隔
Grouping 命令
Shell Script. 概論
這一章, 我們會談到包括一些使用shell script的基本方法, 主要會提到 :
Aliases 別名
Here Documents
一種內嵌於shell script的技巧, 直接用例子說明 :
Job Control 工作控制
工作流程控制, 大概有幾個命令一定得先了解, 包括了 :
所以希望參考完這個例子, 你就能對Job Control工作流程控制有些瞭解.
變數定義
變數在shell script裡面扮演很重要的腳色, 會寫程式的都應該知道變數的定義, 其重要性, 也不用我多說, 我們這邊會包括以下幾部分 :
還是直接用例子來說明, 最容易瞭解. 底下這些都是變數定義的方式(在/bin/bash或者/bin/sh環境下) :
保留/系統預設的變數
系統預設已經有相當多的變數定義了, 因此在你的shell script裡面要去避免這些變數. 以下就是一些預設的系統變數.
shell的判斷式
迴圈 for while loop
sed 字串編輯器
awk 結構化的資料處理工具
範例 (未完成)
版權說明
前言
底下的教學與心得分享是假設你已經有著基本的UNIX or Linux觀念 與技巧, 同時我們利用Linux預設提供的bash shell來操作, 例如 :
- - login in
- - "basic" commands (ls, mkdir..etc)
- - how to move around the system(with cd command)
- - 使用 vi
基本觀念與操作
建立第一個shell script
$ pwd /home/xfish/bin $ ls myscript. myscript2 $ cat myscript. ls -aF $ myscript. bash: ./myscript. Permission denied $ chmod +x myscript. $ myscript. ./ ../ myscript* myscript2* shell script其實就是一個很簡單的文字檔案, 檔案裡面有著 可以操作與控制相關動作與命令, 同時它必須具備能夠執行的能力, 在UNIX與Linux環境下, 也就是必須有 +x 的屬性 上面是一個很簡單的shell script, 簡單地列出目前目錄下的檔案. 同時由於Linux/UNIX底下有多種shell的編譯器, 我們也可以在該script. 中的第一行來指定利用特定的編譯器執行, 例如我們可以指定 : #!/bin/bash 使用echo命令 echo是用來顯示輸出的命令, 用幾個範例做個解釋, 後面的章節 將會看到常常利用echo來做些輸出的動作 : $ echo a b c a b c $ echo "a b c" a b c $ echo $0 -bash (說明, 這個會依照你使用的shell不同而改變) 同時echo還能搭配以下特殊符號來控制特別輸出 : \a alert, beeps the bell \b backspace character \c suppresses the new line \f formfeed character \n new-line \r return character \t tab character \v vertical tab character \\ single backslash character
起始檔案 startup files
跟以往的DOS相同, 使用者登入後, 系統的shell在讀取完系統的 設定檔後(/etc/profile), 會自動讀取使用者shell, 例如 : $HOME/.bashrc 或者 $HOME/.profile 因此, 若有一些需要使用者登入後就執行或者設定的動作, 可以在這 兩個檔案作設定的起始檔案
命令區隔
若有同時兩個命令要執行, 必須使用 ; 來區隔 $ date who (錯誤) date: bad conversion $ date ; who (正確) Tue Aug 25 15:38:24 2005 xfish tty00 Aug 25 15:30 root ttyp1 Aug 25 10:00 $ cd bin ; pwd /home/xfish/bin $ cd .. ; pwd /home/xfish
Grouping 命令
利用( ) 來整合命令, 例如 : $ pwd /home/xfish $ ( cd /bin ; pwd ) /bin $ pwd /home/xfish $ ls -l /usr/bin ; ls -l /usr/share | wc -l 這樣會列出 /usr/bin 與/usr/share 目錄下的檔案, 但是 事實上我們只要算算這總共有多少命令, 因此我們可以利用下面的命令取代 : $ (ls -l /usr/bin ; ls -l /usr/share ) | wc -l 185 $
Shell Script. 概論
這一章, 我們會談到包括一些使用shell script的基本方法, 主要會提到 :
- Aliases 別名
- Here Documents 可以說是一種內嵌的檔案
- Job Control 工作控制
Aliases 別名
直接在命令提示符號下 : alias 命令 , 你就可以看到目前定義的 alias. 而alias就是常常用來把一大串命令縮寫的常用技巧. 比如說我喜歡ls的時候加上ls -F選項, 同時我希望打ls時候預設就帶入 -F 引數, 就可以利用 : $ alias ls='ls -F' 來達到你的目的 多看幾個例子 : $ alias lf="/usr/bin/ls -CaF" $ alias rm=echo $ rm /tmp/junk /tmp/junk
Here Documents
一種內嵌於shell script的技巧, 直接用例子說明 :
$ cat phone #!/bin/bash grep -i $1 << END A Company 404 123 5888 Rosebery Corp. 314 713 7639 Chedworth.com 212 987 6543 Atlanta.Net 770 111 2222 END $ phone atla Atlanta.Net 770 111 2222 (這是輸出結果) 另外, END 那個只是一個識別, 也就是說, 你可以用其他字元代替, 不過還是建議用單字或者字串做為識別, 而不要用符號
Job Control 工作控制
工作流程控制, 大概有幾個命令一定得先了解, 包括了 :
- jobs [-lp] [job]
- bg [job..]
- fg [job..]
- kill [-signal] job..
- wait [job..]
- %number : refer to job by number
- %string : job whose name begins with string
- %?string : job whose name contains string
- %+ or %% : current job
- %- : previous job
所以希望參考完這個例子, 你就能對Job Control工作流程控制有些瞭解.
$ stty susp ^Z (確保 susp 是 ^Z (Ctrl + Z)) $ stty tostop $ ls -R / (這個命令可以讓系統跑很久, 按下 Ctrl + Z) ^Z [1]+ Stopped ls -R / (系統提示這個編號 1 的 job 被 stopped) $ bg (執行 bg 命令, 把編號 1 丟到後端去跑) [1]+ ls -R / & $ (sleep 36 ; echo Hello World) & (執行第二道命令) [2] 656 (系統給編號 2 的命令) [1]+ Stopped ls -R / $ jobs (利用 jobs 命令 檢視所有後端工作) [1]- Stopped ls -R / [2]+ Stopped (sleep 36;echo Hello World) $ kill %- (刪除前一編號的工作) [1]- Stopped ls -R / $ jobs (利用 jobs 命令 再次檢視所有後端工作) [1]- Terminated ls -R / [2]+ Stopped (sleep 36; echo Hello World) $ fg %2 (把編號 2 命令帶到 前端 ) (sleep 36; echo Hello World) Hello World (列印出 結果 並結束 ) $
變數定義
變數在shell script裡面扮演很重要的腳色, 會寫程式的都應該知道變數的定義, 其重要性, 也不用我多說, 我們這邊會包括以下幾部分 :
- 變數的定義
- 保留/系統預設的變數
還是直接用例子來說明, 最容易瞭解. 底下這些都是變數定義的方式(在/bin/bash或者/bin/sh環境下) :
$ name=Derek $ fullname='Derek Super' $ completename="Derek Super Man" $ echo my name is $name, $fullname, $completename my name is Derek, Derek Super, Derek Super Man $ $ question='What is "sheckle"' $ echo my question is $question my question is What is "sheckle" $
保留/系統預設的變數
系統預設已經有相當多的變數定義了, 因此在你的shell script裡面要去避免這些變數. 以下就是一些預設的系統變數.
BASH_ENV absolute path of startup file CDPATH directories searched by cd FCEDIT absolute path of history editor HISTCMD the history number of the current command HISFILE absolute path of history file HISTSIZE number of remembered commands HOME login directory IFS token delimiters LINENO current line number in shell script. LINES terminal height MAIL absolute path of mailbox MAILCHECK number of seconds to check mail OLDPWD absolute path of previous directory OPTARG option set by getopt OPTIND option's ordinal position set by getopt OSTYPE the OS on which bash is executing PATH command search path PPID process ID of parent PS1 primary prompt PS2 secondary prompt PWD absolute path of current directory RANDOM random integer REPLY default variable for read SECONDS number of seconds since shell started SHELL absolute pathname of preferred shell TMOUT seconds to log out after lack of use UID user ID of the current user $ process ID of current shell ? exit status of most recent statement 還有一些常用的 符號變數, 分列如下 : $# 引數的數目 $* 代表所有引數 $? Exit status of previous command $$ PID of this shell's process $! PID of the most recently started backgroup job
shell的判斷式
從這邊開始, 我們將開始進入一些shell script的判斷, 就是說 我們會利用到if-then-else的一些判斷, 來讓shell script具備判斷能力. 討論的主題預計包括 :
- If-Then-Else 敘述
- Testing 判斷式
- Case 敘述
Testing 判斷式通常與if-then-else一起互用, 以便發揮其效果. 先從一個最簡單的例子看起 : $ cat myscript7 #!/bin/sh if [ -f /etc/passwd ]; then echo "/etc/passwd is a file" else echo "PANIC : /etc/passwd is not a file!!" fi 先說明一下 [ -f /etc/passwd ] 這個最重要的部份, [ ] 裡面 就是判斷式, 而這裡是判斷 /etc/passwd 是不是一個 file ? 由結果來看看是執行 then 下面的敘述, 或者執行 else 的敘述. 同時很重要一點是 底下這些敘述都是不正確的敘述, 會有錯誤產生喔 : [-f /etc/passwd ] [-f 連在一起 [ -f /etc/passwd] passwd] 連在一起 [ -f/etc/passwd ] -f與/etc/passwd連在一起 所以利用 [ ] 我們可以做出以下這些判斷, 這些也都很常用喔 !! test true if ....case 敘述
[ string1 = string2 ] string1 and string2 are equal [ string1 != string2 ] string1 and string2 are not equal [ string1 \< string2 ] string1 is lexically less than string2 (e.g. 'a' is less than 'b') [ string1 \> string2 ] string1 is lexically greater than string2 (e.g. 'b' is greater than 'a') [ -z string ] string is zero (e.g. a empty string) [ -n string ] string is nonzero (e.g. a VAR string) [ -e file ] file exists [ -f file ] file is a file [ -d file ] file is a directory [ -c file ] file is a character device [ -b file ] file is a block device [ -p file ] file is a named pipe [ -s file ] file is not empty [ -k file ] file's sticky bit is set [ -S file ] file is a socket [ -L file ] file is a symbolic link [ -r file ] file is readable by user [ -w file ] file is writeable by user [ -x file ] file is executeable by user [ -O file ] file is owner by user [ -G file ] file is group owned by a greoup [ -u file ] file has its set user ID bit set [ -g file ] file has its group user ID bit set [ file1 -nt file2 ] file1 is newer than file2 [ file1 -ot file2 ] file1 is older than file2 [ file -ef file2 ] file1 is another name for file2 [ n1 -eq n2 ] true if integer n1 = integer n2 [ n1 -ne n2 ] true if integer n1 <> n2 [ n1 -gt n2 ] true if n1 > n2 [ n1 -ge n2 ] true if n1 >= n2 [ n1 -lt n2 ] true if n1 < n2 [ n1 -le n2 ] true if n1 <= n2
case 敘述與 if-then-else 效用類似, 請參考下述例子 : $ cat myscript9 #!/bin/sh case $1 in [a-z]*) echo "starts with lower case" ;; [A-Z]*) echo "starts with upper case" ;; ?*) echo "starts with something else" ;; *) echo "doesn't start" esac case敘述是由 case 開頭與 esac (case的到寫) 組合而成, 而每一個 判斷之後的兩個分號 (;;) 就是代表 break 的功能, 也就是說遇到 ;; 就會跳出整個 case 判斷式. 而上述的範例能夠判斷script所附帶的引數, 若引數為小寫字母開頭, 則印出 "starts with lower case", 反之若是大寫字母開頭, 則印出 "starts with uppper case". 再用一個簡單的例子說明 : $ cat myscript10 #!/bin/sh case $1 in 0) echo zero ;; 1) echo one ;; 2) echo two ;; 3) echo three ;; 4) echo four ;; 5) echo five ;; 6) echo six ;; 7) echo seven ;; 8) echo eight ;; 9) echo night ;; *) echo $1 ;; esac
迴圈 for while loop
迴圈的宣告基本上所有的語言都是類似, 也就是都靠 while, until 或者 for 這兩個方法來做迴圈. while迴圈 $ cat myloop1 #!/bin/sh read -r filename while [ ! -f $filename ]; do echo "--> $filename does not exist" read -r filename done echo "$filename name OK" $ myloop1 /etc/password --> /etc/password does not exist /etc/groups --> /etc/groups does not exist /etc/group /etc/group name OK $ 說明 : 執行後, 會等待使用者輸入一個檔名, 接著會檢查 該輸入字串是否真為一個檔案 (利用 -f 判斷), 若是 則跳出 while loop 並且印出 "檔名 name OK" 反之, 則印出 "--> 檔名 does not exist" , 並繼續 要求使用者輸入. until 迴圈 同 while , until 的功用與語法很類似, 請參考 $ cat myloop2 #!/bin/sh until who | grep dino > /dev/null; do sleep 10 done echo "dino has logged in" $ myloop2 & [2] 9281 $ $ $ dino has logged in 我們再用一個例子來讓迴圈多點變化 : $ cat myloop3 #!/bin/sh i=1 while [ $i != 7 ]; do echo $i i=`expr $i + 1` done $ myloop3 1 2 3 4 5 6 $ 這個範例 我想就不用怎麼說明瞭, 不過利用這個範例 跟大家分享一下, 我常常用來做倒數計時的一個迴圈 : #!/bin/sh interval=10 total=1 while [ $total -le 5 ]; do i=1 while [ $i -le $interval ]; do echo -e "$total / $i / $interval \r\c" sleep 1 i=`expr $i + 1` done total=`expr $total + 1` done 請大家試試 就可以知道 這大概是什麼用的, 不過有時候 echo 的語法 似乎在各種不同的 shell (e.g. /bin/sh, /bin/bash) 之間 並不完全相同 這可能要花一點點時間去確認的. for 迴圈 繼續談到 for 迴圈, for 迴圈通常使用在比較有明確範圍的情況. 例如 : $ cat myloop4 #!/bin/sh for foo in *; do if [ -f $foo ]; then echo "$foo is a file" elif [ -d $foo ]; then echo "$foo is a directory" else echo "$foo is not a file, nor directory" fi done $ myloop4 snake.txt is a file tab.txt is a file tinrc.txt is a file tmp is a directory tmp1 is a file
sed 字串編輯器
這部份要先偷懶一下, 因為之前已經寫過一些 sed 的簡易說明, 這裡直接把它拿過來, 同時加上一些補充.
- 將 filename 檔案內的 Giga 字串取代成 GigaRama sed s/Giga/GigaRama/ filename 但是我們這樣只能做 stdout , 若是要把 file1 裡面的 Giga 都取代成 GigaRama 的話, 我們可以這樣做 : cat file1 | sed s/Giga/GigaRama/ > file2
- 將 filename 檔案內的 xfish 字串那一行刪除 sed /xfish/d filename 同樣, 若是要將修改過的檔案變成一個新檔案, 可以這樣做 : cat file1 | sed /xfish/d > file2
- 指定哪一行,將之刪除 sed '4d' filename 這裡是指定第四行 刪除
- 將filename的第一行到第幾行,將之刪除 sed '1,4d' filename 這裡是指定第一行到第四行 刪除
- 將filename的第一行到第五行印出 sed -n 1,5p filename
- 將 file 檔案內的出現 xfish 字串的那一行單獨寫到 file2 內 sed -n '/xfish/w file2' file
- 萬用字元的使用,將 file 檔案內的 xfis? 哪一行寫到 file2 內 sed '/xfis./w file2' file
- 萬用字串的使用,將 file 檔案內的 xfis* 哪一行寫到 file2 內 sed '/xfis*/w file2' file
- 選定字元的使用,將 file 檔案內的 xfis[abcd] 哪一行寫到 file2 內 sed '/xfis[abcd]/w file2' file
- 特別符號的取消,利用 / sed s/\/\/ file
- 一行的起頭的取代,將 file 檔案的每一行起頭都加上 Hi.. sed s/^/Hi.. / file
- 一行的結尾的取代,將 file 檔案的每一行結尾都加上 Hi.. sed s/$/Hi.. / file
- 多重條件的指定,利用 -e 選項 sed -e 's/Giga/GigaRama/' -e 's/^/Hi../' file
awk 結構化的資料處理工具
(未完成)
範例 (未完成)
這些部分都是我自己寫的例子, 可能不完全正確, 或者說 還有很多可以改進的地方, 如果有任何建議, 請給我email. 還有一些部份是直接從網路上收集的, 挑幾個作一些參考. 另外, 若你有什麼好的script, 願意一起放進來, 我都很歡迎喔.:)
- 把目錄下大寫的檔案名稱 修改成小寫的檔案名稱 #!/bin/sh for file in [A-Z]*; do echo "processing $file" mv $file `echo $file | tr '[A-Z]' '[a-z]'` done
- 修改檔名, 把 *.htm 修改成 *.html 這個在DOS下可能用一個 rename 就可以解決了, 但是很抱歉 UNIX/Linux上面可不行. 所以 shell script. 就可以幫上忙了. #!/bin/sh for i in *.htm ; do echo "processing $i" mv $i `basename $i .htm`.html done
- 輸入 mycmd f1 f2 f3 f4 .. fn 把每個 f* 複製成 f*.bak 利用 while 與 shift 的技巧 : #!/bin/sh while [ $# -gt 0 ]; do # 註解 把 echo 拿掉 就真的變成命令了.. # 這裡只有 echo 出來 並沒真正執行 echo "cp $1 $1.bak" shift done
- 系統登入後 提示選單 選擇連上 PTT BBS (2007/03/22新增) 這是懶人的做法, 就是登入login系統後, 出現一個選單, 選單內 讓你能夠選擇連上 PTT BBS , 並且自動登入 PTT BBS , 這個有利用 expect , 也就是hacker喜歡用的一個工具 , 直接看例子吧 : 檔案 1 : 命名 bbs.sh #!/bin/bash while [ 1 ]; do clear echo "===================================================" echo " (1) PTT BBS " #註解:我只給一個選項 for test echo " (q) QUIT " #註解:要更多 請自己加 echo " (0) 離開選單 " #註解:要更多 請自己加 echo "===================================================" echo -n "your choice? ==> " read ans case $ans in 1) ptt.expect #註解:所以你還必須有個 ptt.expect 檔案 ;; q) kill -9 $MY_PID #註解:這個必須在你的 .login 中註明 ;; 0) exit ;; *) echo "Please choose the number from the list" ;; esac done 檔案結束 檔案 2 : 命名 ptt.expect #系統必須安裝expect套件喔 #!/usr/local/bin/expect -- #註解:路徑請自行修改喔 set host 140.112.90.72 #註解:這裡是ptt.cc的 IP , 用ptt.cc也OK spawn telnet $host expect "入代號" send "superman\r" #註解:把你的帳號名稱放這裡 expect "輸入您的密" send "supermanisgoodboy\r" #註解:把你的密碼放這裡 send "\r" interact 檔案結束 檔案 3 : $HOME/.login or $HOME/.bashrc or $HOME/.tcshrc 依照你自己設定 看看你一進入系統會讀取哪個檔案 我只有用兩行 說明 當然你可能還有自己的變數 or 設定 export MY_PID $$ #註解:這個是給 bbs.sh 用的 bbs.sh #啟動剛剛的 bbs.sh 路徑自己寫. 檔案結束
版權說明
本份學習講義, 是根據Caldera System出版的LINUX SHELL SCRIPTING所 整理而成的檔案, 這份講義, 內容除了本身所提供外, 很多範例與說明都是 由該本書擷取出來, 因此我覺得我只是整理出來. 雖然有加上我自己的一些 經驗與自己寫的一些 script, 但是為了尊重原本製作的公司與個人. 所以我只擁有檔案整理權. 許景超 - Last update : 2005/11/11 -
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/82392/viewspace-175136/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 鍵盤錄入求絕對值
- Linux Shell獲取正在執行指令碼的絕對路徑Linux指令碼
- shell請求api,獲取json返回值,做判斷APIJSON
- 去掉pipeline中shell命令的除錯資訊除錯
- Python中求絕對值的三種方法詳解!Python
- shell生成測試資料
- shell查詢prometheus資料Prometheus
- Shell 命令求兩個檔案每行對比的相同內容
- SHELL之數值運算
- shell study-3day--shell變數及例項3D變數
- Linux shell——列印不為0的行Linux
- shell-----資料呈現方式
- bash shell 程式與磁碟資料
- Shell程式設計-04-Shell中變數數值計算程式設計變數
- shell指令碼報錯:[: missing `]‘指令碼
- shell 變數賦值問題變數賦值
- shell變數命名與賦值變數賦值
- 總結一篇shell除錯技巧及常見的指令碼錯誤除錯指令碼
- [shell]shell指令碼實現每天自動抽取資料插入hive表指令碼Hive
- Jenkins Tips:去掉pipeline中shell命令的除錯資訊Jenkins除錯
- Shell:子shell概念
- 關於Shell 的幾個冷門資料
- MySQL資料庫備份的shell指令碼MySql資料庫指令碼
- shell監控mysql 8.0資料庫MySql資料庫
- shell監控mysql 5.7資料庫MySql資料庫
- 使用shell 指令碼備份資料指令碼
- shell初級-----資料呈現方式
- 強大好用的shell之shell命令
- 【SHELL】Shell中的條件判斷
- Shell階段09 shell正則,grep正則, sed使用及案例
- python 呼叫 shell ,獲取返回值和返回資訊Python
- shell指令碼:批次傳送curl請求指令碼
- Liunx備份mysql資料庫的shell指令碼MySql資料庫指令碼
- MySQL Shell import_table資料匯入MySqlImport
- shell——shell輸入輸出
- 使用 adb shell dumpsys gfxinfo 和 adb shell dumpsys SurfaceFlinger --latency 都無法獲取到資料
- nameko shell 報錯 : [Errno 111] Connection refused
- Shell:常見錯誤總結(一)