文/一介書生,一枚碼農。
scripts are for lazy people.
函數是存在內存里的一組代碼的命名的元素。函數創建於腳本運行環境之中,並且可以執行。
函數的語法結構為:
function <function-name> {
<code to execute>
}
創建函數不需要do
或 done
這些關鍵字,只需要大括號來界定函數的作用范圍。
我們可以在命令行中創建一個簡單的函數:
function show_system {
echo "The uptime is:"
uptime
echo
echo "Current dir:"
pwd
echo
echo "Date:"
date
}
在命令行定義上面的函數:
然后執行函數:
最后,我們可以使用type
命令查看函數的定義:
方法可以有傳遞的參數。在此之前,我們先簡單介紹 sed
命令,下面的腳本用來移除文件中的注釋行和空白行。
sed -i.bak '/^\s*#/d;/^$/d' <filename>
詳細介紹一下上面的腳本:
sed -i.bak
:sed 命令會創建一個以.bak
結尾的備份文件,用來備份原始的文件。/^
:表示行首。\s*
:匹配任何不可見字符,包括空格、制表符、換頁符等。#/
:shell 腳本中的注釋標記。/^\s*#/
一起使用用來查找注釋行和帶有不可見字符的注釋行。d
:用來刪除匹配的行。;/^$/d
:;
是表達式的分隔符,后面的表達式跟前面的表達式意思很像,用來刪除空白行, "$"匹配輸入字符串的結束位置。
我們把上面的腳本移到函數中,創建一個名為clean_file
的函數:
function clean_file {
sed -i.bak '/^\s*#/d;/^$/d' "$1"
}
上面的代碼中,我們使用位置參數$1
來接收命令行里傳遞的參數,需要注意的是$1
用大括號來括起來。
下面,我們完善clean_file
方法,新建一個腳本文件 clean.sh。代碼如下:
#!/bin/bash
# Script will prompt for filename
# And remove commented and blank lines
function is_file {
if [ ! -f "$1" ] ; then
echo "$1 does not seem to be a file"
exit 2
fi
}
function clean_file {
is_file "$1"
BEFORE=$(wc -l "$1")
echo "The file $1 starts with $BEFORE"
sed -i.bak '/^\s*#/d;/^$/d' "$1"
AFTER=$(wc -l "$1")
echo "The file $1 is now $AFTER"
}
read -p "Enter a file to clean: "
clean_file "$REPLY"
exit 1
其中,wc -l
命令用來打印文件行數。
現在,我們新建一個用來測試的文件 test.txt,里面隨便寫些內容:
# This file is just for testing.
Hello.
World.
# new comment.
$
The end.
在 test 文件所在的目錄下,執行 clean.sh腳本:
然后查看 test 文件和 test.bak 文件,發現空白行和注釋行已經刪除。
這里需要注意的是,shell 腳本是從上至下來執行的,如果在一個函數中調用了另一個函數,那么被調用的函數要定義在調用函數的前面。
當然,除了函數可以傳遞參數外,還可以有返回值。默認情況下,在執行完函數內的最后一行代碼后,方法會返回一個狀態的數字,你可以使用$?
變量來查看函數執行的狀態。如果返回值為0,表示方法正常退出,非0表示程序發生錯誤或其他非正常退出。
我們使用return
關鍵字來返回一個整數。這里需要注意兩點:
- 函數一旦執行完就會返回狀態代碼。
- 狀態代碼的范圍為0到255。
如果不想返回函數的狀態代碼,而是想返回一個字符串或是其他類型,可以使用 echo 變量
的方式來返回值。
下面創建腳本文件 translate.sh,用來把文件中的大寫字符轉換為小寫字符:
#!/bin/bash
# Script that translates upper letter to low letter
function to_lower ()
{
input="$1"
output=$(tr '[A-Z]' '[a-z]' <<< "$input")
echo $output
}
while true
do
read -p "Enter c to continue or q to exit: "
result=$(to_lower $REPLY)
echo "After translate: $result"
if [ $result = "q" ] ; then
break
fi
done
echo "Finished"
代碼會把輸入的大寫字符變成小寫字符,當輸入"Q"或"q"時程序退出。