1. 程式人生 > >shell淺談之十一別名、列表及陣列

shell淺談之十一別名、列表及陣列

一、簡介

Shell中別名可以對命令進行重新命名,方便使用者記憶長命名和定製自己熟悉的工作環境;列表是一組命名以邏輯與、邏輯或的關係串在一起,實現指令碼程式的邏輯控制;陣列是一重點,涉及陣列的賦值、操作和字串的處理,以及利用陣列實現堆疊和二維陣列等資料結構的儲存。

二、詳解

1、別名

       對linux命令重新命名,主要考慮到很多linux命令帶有冗長的選項和引數,頻繁使用這些長命令極易造成使用者使用上的不便。別名的命令關鍵字是alias,基本格式為alias name='original-command'(等號兩邊不能有空格)。如alias ipconfig=ifconfig。若要刪除已經設定的別名,使用內建命令unalias,unalias -a表示刪除所有已設定的別名,unalias alias-name表示僅刪除alias-name別名。

#!/bin/bash

shopt -s expand_aliases   #開啟expand_aliases選項
alias detail="ls -l"
detail /root/in*          #別名支援萬用字元*
echo
directory=/root/
prefix=in*
alias vardetail="ls -l $directory$prefix"   #雙引號和單引號在處理空格時是等價的,
                                            #但設定vardetail引用了變數,此處只能使用雙引號
vardetail

echo "Deleting all aliases:"
unalias -a                #刪除所有的別名
detail
vardetail
      若要在指令碼中使用別名功能,必須在指令碼使用shopt -s expand_aliases命令開啟expand_aliases(表示別名可以被擴充套件)選項,未開啟,alias命令建立的別名不會執行。

      要注意的是:在諸如if/then結構、迴圈和函式等混合型結構中不能使用alias命令設定別名,但可以執行在混合型結構之外所設定的別名。

2、列表

(1)shell中列表是由一串命令用與運算(&&)和或運算(||)連線而成,分別稱為與列表和或列表。與列表的格式為:命令1 &&命令2&& 命令3 &&... &&

命令n,從左到右依次執行命名,直到某命令返回FALSE時(退出狀態為非0)與列表執行終止。或列表的格式為:命令1 || 命令2 || 命令3 ||... ||命令n,從左到右依次執行命名,但是當某命令返回TRUE時(退出狀態為0)或列表執行終止。

(2)與列表控制輸入引數個數和返回狀態碼

#!/bin/bash

MAXARGS=3
ERROR=68
test $# -ne $MAXARGS  && echo "Usage: `basename $0` $MAXARGS arguments" && exit $ERROR
echo "Less than $MAXARGS arguments are passed to this script."
exit 0

(3)或列表控制輸入引數個數和返回狀態碼

#!/bin/bash

MAXARGS=3
ERROR=68
test $# -eq $MAXARGS  || (echo "Usage: `basename $0` $MAXARGS arguments" && false) || exit $ERROR
echo "Correct arguments are passed to this script."
exit 0
      可以對比或列表和與列表的語句,由於echo命令總是返回TRUE,要將echo和false進行與運算從而返回FALSE值。其中test命令實際上是或列表的巢狀,在使用與或列表巢狀時需要利用圓括號區分邏輯運算的優先順序。

3、陣列

 (1)賦值和取值

       陣列(Array)是一個由若干同類型變數組成的集合,陣列均由連續的儲存單元組成,最低地址對應於陣列的第一個元素,最高地址對應於最後一個元素。Shell只支援一維陣列,array[x]表示array陣列的第x+1個元素,支援的最大數值標號是599 147 937 791。shell取得陣列值(引用陣列元素)格式是:${array[x]}

#!/bin/bash

city[0]=Nanjing      #對第1、2個數組元素賦值
city[1]=Beijing
city[9]=Melbourne    #對第10個數組元素賦值
city[15]=NewYork     #對第16個數組元素賦值

echo "city[0]=${city[0]}"
echo "city[1]=${city[1]}"
echo "city[9]=${city[9]}"
echo "city[15]=${city[15]}"
echo "city[2]=${city[2]}"    #未初始化陣列的值為空
echo "city[10]=${city[10]}"

Shell中允許陣列空缺元素,即可以不連續地給陣列賦值。還可以用圓括號將一組值賦給陣列。

#!/bin/bash

city=(Nanjing Beijing Melbourne NewYork)    #圓括號內以空格為分隔符,依次賦給陣列元素

echo "city[0]=${city[0]}"
echo "city[1]=${city[1]}"
echo "city[2]=${city[2]}"
echo "city[3]=${city[3]}"
echo "city[4]=${city[4]}"       #未被初始化輸出空
echo "city[5]=${city[5]}"
#!/bin/bash

city=(Nanjing [10]=Atlanta Massachusetts Marseilles)  #指定所賦元素的標號,並以此標號為起點繼續賦值

echo "city[0]=${city[0]}"       #city[0]=Nanjing
echo "city[1]=${city[1]}"       #city[1]=
echo "city[10]=${city[10]}"     #city[10]=Atlanta
echo "city[11]=${city[11]}"     #city[11]=Massachusetts
echo "city[12]=${city[12]}"     #city[12]=Marseilles
echo "city[13]=${city[13]}"     #city[13]=
既然圓括號內允許對陣列指定元素進行賦值,那麼完全可以按照任意順序指定任意元素對陣列賦值。例如:
city=([2]=Nanjing [10]=Atlanta [1]=Massachusetts [5]=Marseilles)
(2)位置引數中[email protected]和$*都表示傳遞到指令碼的所有引數,在陣列中@和*的應用是列印陣列的所有元素。
#!/bin/bash

city=(Nanjing Beijing Melbourne NewYork)

for i in ${city[@]}  #等價於  for i in ${city[*]}
do                   #列印陣列的所有元素
echo $i
done
#!/bin/bash

city[1]="Hong Kong"       #用引號包含空格的字串
city[100]=Massachusetts
city[101]="New York"
city[10000]=Atlanta

for i in "${city[@]}"
do
echo $i
done
      由於city陣列元素包含了空格,因此需要使用引號將${city[@]}引起來,for迴圈和@只打印被賦值的元素而不列印未賦值的元素。

      注意:"${city[@]}"將陣列的所有元素分行列印,而"${city[*]}"只能將陣列的所有元素列印在一行內且中間以IFS分隔。不用引號時${city[@]}和${city[*]}是等價的,使用引號時,@和*只是列印陣列的方式存在差異。
(3)陣列的用法

       陣列的字串操作與字串操作的符號和意義完全一致,陣列字串操作特殊之處在於所有的操作都是針對所有的陣列元素逐個進行的。

#陣列的字串操作
#!/bin/bash

city=(Nanjing Atlanta Massachusetts MaseillesMas)

echo "Extracting Substring"  #抽取字串
echo ${city[*]:0}            #抽取整個陣列  Nanjing Atlanta Massachusetts Marseilles
echo ${city[*]:1}            #抽取從第1個元素到結束的陣列  Atlanta Massachusetts Marseilles
echo ${city[*]:3}            #抽取從第3個元素到結束的陣列  Marseilles
echo ${city[*]:0:2}          #抽取從第0個元素開始的兩個元素  Nanjing Atlanta
echo
echo "Removing Substring"    #刪除字串
echo ${city[*]#M*a}          #刪除匹配M*a的最短字串  Nanjing Atlanta ssachusetts rseilles
echo ${city[*]##M*a}         #刪除匹配M*a的最長字串  Nanjing Atlanta chusetts rseilles
echo
echo "Replcing Substring"    #替換子串功能
echo ${city[*]/M*s/Year}     #替換第1次與M*a匹配的子串  Nanjing Atlanta Year Year
echo ${city[*]//Mas/Year}    #替換所有與Mas匹配的子串   Nanjing Atlanta Yearsachusetts YeareillesYear
                             #替換的正則為最長匹配
      陣列也可以存放read命令所讀入的使用者輸入引數,declare -a city(並不是必須的)將city申明為陣列,用read -a city命令將輸入儲存到city陣列之中,輸入以空格分開。可以使用unset city[0]命令清空一個元素,和unset city清空整個陣列。使用${#city[@]}獲取陣列的長度。

      shell陣列的一種重要操作:陣列連線。

#!/bin/bash

city=(Beijing Nanjing Shanghai)
person=(Cai [5]=Wu Tang)             #陣列不連續地賦值

declare -a combine                   #宣告combine陣列
combine=(${city[@]} ${person[@]})    #combine是陣列city和person的連線,連線操作將不連續的元素按序存放到combine陣列中

element_count=${#combine[@]}         #while迴圈輸出combine陣列
index=0
while [ "$index" -lt "$element_count" ]
do
   echo "Element[$index]=${combine[$index]}"  #陣列標號與值的對應關係
   let "index=$index+1"
done
###################
echo
unset combine                                 #清空combine陣列
combine[0]=${city[@]}                         #將city陣列賦給combine[0]的一個元素
combine[1]=${person[@]}                       #將person陣列賦給combine[1]的一個元素
element_count=${#combine[@]}
index=0
while [ "$index" -lt "$element_count" ]
do
   echo "Element[$index]=${combine[$index]}"
   let "index=$index+1"
done
###################
echo
declare -a subcombine=${combine[1]}          #宣告陣列時賦值
element_count=${#subcombine[@]}
index=0
while [ "$index" -lt "$element_count" ]
do
   echo "Element[$index]=${subcombine[$index]}"
   let "index=$index+1"
done

(4)陣列實現簡單的資料結構

      資料結構是指相互之間存在一種或多種特定關係的資料元素的集合,它直接影響到程式的執行速度和儲存效率。Shell不直接支援如堆疊、佇列、連結串列等資料結構,但可以很容易實現線性資料結構。對於樹形、圖等複雜的資料結構,shell理論上可以實現,但難度角度。

      利用陣列實現堆疊操作。push函式將字串壓入堆疊,pop函式能彈出棧頂元素,status函式列印當前堆疊的狀態資訊。其中shift命令完成兩個功能:第一,所有位置引數左移1位,即$2移動到$1的位置,$3移動到$2的位置,依次類推($0不變);第二,$#變數值減1。

#!/bin/bash

MAXTOP=50               #堆疊能存放元素的最大值

TOP=$MAXTOP             #棧頂指標,初始值是$MAXTOP

TEMP=
declare -a STACK        #全域性陣列STACK

push()                  #push進棧操作,可同時將多個元素壓入堆疊
{
		if [ -z "$1" ]      #無引數,返回
		then
			 return
		fi

		#for ((i=1; i<=$#; i++))
		until [ $# -eq 0 ]   #until迴圈將push函式的所有引數都壓入堆疊
		do
				let TOP=TOP-1    #棧頂指標減1

				STACK[$TOP]=$1
				shift            #指令碼引數除$0外左移1位,$#引數總個數減1
		done

		return
}

pop()                     #pop出棧操作,執行pop函式使棧頂元素出棧
{
		TEMP=

		if [ "$TOP" -eq "$MAXTOP" ]   #若堆疊為空,返回
		then
		 return
		fi

		TEMP=${STACK[$TOP]}           #棧頂元素出棧
		unset STACK[$TOP]         
		let TOP=TOP+1                 #棧頂指標加1
		return
}

status()                          #顯示當前堆疊內的元素,以及TOP指標和TEMP變數
{
		echo "==========STACK=========="
		for i in ${STACK[@]}                                
		do
		echo $i
		done
		echo "Stack Pointer=$TOP"
		echo "Just popped \""$TEMP"\" off the stack"
		echo "=========================="
}

push one              #1個元素入棧
status                #顯示狀態
push two three four   #3個元素入棧
status

pop                   #出棧
pop
status
push five six
status

     利用一維陣列模擬實現二維陣列,二維陣列仍儲存在一維陣列中,只是通過行號和列號計算出陣列的索引而已。可以採用該方法使shell指令碼語言用於定義二維陣列和矩陣。

#建立一個二維陣列,並以逐行列印及旋轉45度列印的兩種方式將它打印出來
#!/bin/bash

#定義行數、列數,及陣列名
ROW=5
COL=5
declare -a MATRIX      #申明MATRIX陣列
 
load_alpha ()
{
		local rc=0
		local index
		
		#for迴圈將A-Y這25個字元儲存到MATRIX陣列
		for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y
		do
				local row=`expr $rc / $COL`
				local column=`expr $rc % $ROW`
				let "index = $row * $ROW + $column"
				MATRIX[$index]=$i
				let "rc += 1"
		done  
}
  
print_alpha ()
{
		local row=0
		local index
		
		#逐行列印MATRIX陣列
		while [ "$row" -lt "$ROW" ] 
		do                           
				local column=0
				echo -n "       " 
				while [ "$column" -lt "$COL" ]
				do
						let "index = $row * $ROW + $column"
						echo -n "${MATRIX[index]} " 
						let "column += 1"
				done
				let "row += 1"
				echo
		done
	  echo
}
  
filter ()     # 過濾掉負的陣列下標. 
{
		echo -n "  "  # 產生傾斜. 
		              # 解釋一下, 這是怎麼做到的. 
		
		if [[ "$1" -ge 0 &&  "$1" -lt "$ROW" && "$2" -ge 0 && "$2" -lt "$COL" ]]
		then
		    let "index = $1 * $ROW + $2"
		    # 現在, 按照旋轉方向進行列印. 
		    echo -n " ${MATRIX[index]}"
		    # alpha[$row][$column]
		fi    
}
 
rotate ()  # 將陣列旋轉45度 --
{          #+ 從左下角進行"平衡". 
		local row
		local column
		
		for (( row = ROW; row > -ROW; row-- ))
		  do  
		  for (( column = 0; column < COL; column++ ))
		  do
				  if [ "$row" -ge 0 ]
				  then
				    let "t1 = $column - $row"
				    let "t2 = $column"
				  else
				    let "t1 = $column"
				    let "t2 = $column + $row"
				  fi  
				  filter $t1 $t2   # 將負的陣列下標過濾出來
		 done
	 
		echo; echo
		done 
}
 
 #下面利用上述函式建立二維陣列,逐行和旋轉45°列印陣列
 load_alpha     # 載入陣列
 print_alpha    # 列印陣列
 rotate         # 逆時針旋轉45°列印

三、總結

(1)別名、列表及陣列這三個知識點是相對獨立的,可分開理解。

(2)陣列是重點,會使用陣列字串的操作,以及利用陣列實現堆疊和二維陣列等資料結構。

相關推薦

shell別名列表陣列

一、簡介 Shell中別名可以對命令進行重新命名,方便使用者記憶長命名和定製自己熟悉的工作環境;列表是一組命名以邏輯與、邏輯或的關係串在一起,實現指令碼程式的邏輯控制;陣列是一重點,涉及陣列的賦值、操作和字串的處理,以及利用陣列實現堆疊和二維陣列等資料結構的儲存。 二、

shell例項檢測整數浮點數和日期數的合法性

一、問題       實際工作中,經常會碰到對數值的檢測,在此將檢測整數、浮點數和日期的合法性綜合在一起,總結各種不同的檢測方法。特別是日期總結了shell處理日期非常好的方法,可以借鑑使用,每個函式都可以根據需要獨立提取出來。 二、詳解 (1)檢測輸入整數的合法性

shell三forwhileuntil迴圈

一、簡介 Shell程式設計中迴圈命令用於特定條件下決定某些語句重複執行的控制方式,有三種常用的迴圈語句:for、while和until。while迴圈和for迴圈屬於“當型迴圈”,而until屬於“直到型迴圈”。迴圈控制符:break和continue控制流程轉向。

Qt二:拖拽文字圖片

一、簡介        首先選擇窗體顯示風格,接著顯現拖拽效果,文字和圖示都可以作為拖拽的物件,在窗體中的文字圖示可以拖拽到視窗的任意位置,它們在兩個獨立執行的程式間也可相互拖拽(此時是複製一份到拖拽目的程式視窗中),文字拖拽的範圍更廣(須注意字符集的轉換)。本文解決這種

Qt六:TCP和UDP(之一)

一、簡介        Qt使用QtNetwork模組來進行網路程式設計,提供了一層統一的套接字抽象用於編寫不同層次的網路程式,避免了應用套接字進行網路編的繁瑣(因有時需引用底層作業系統的相關資料結構)。有較底層次的類如QTcpSocket、QTcpServer和QUdp

安裝系統 UEFI和LegacyUEFI+Legacy啟動的區別

uefi和legacy是兩種不同的引導方式, uefi是新式的BIOS,legacy是傳統BIOS。你在UEFI模式下安裝的系統,只能用UEFI模式引導;同理,如果你是在Legacy模式下安裝的系統,也只能在legacy模式下進系統。uefi只支援64為系統且磁碟分割槽必須為gpt模式,傳統BIOS

三大文件——需求概要詳細

        當今,電腦已經走進了千家萬戶。而用360清理電腦,好像已經是每家每戶經常乾的事情。而我的一個遠親更為誇張,家裡電腦上裝滿了360的套裝。從瀏覽器到安全衛士再到防毒軟體。清理電腦清理的頻

Qtlog調試日誌

gms 生成文件 _file__ ica 沒有 rest delet mar 排除 一、簡單介紹 近期因調試code時,想了解程序的流程,但苦於沒有一個簡易的日誌記錄,不停使用qDebug打印輸出,而終於提交代碼時得去多次刪除信息打印,有時還會出現新改動

QtQT_OpenGL

一、簡介           最近想了解些Qt的OpenGL程式設計,可能以後會使用。Opengl是對2D和3D圖形支援很好,有非常多的優化函式,而且是個跨平臺的開源庫。Qt的Opengl封裝的很好,通過Qt的QGLWidget類,將opengl的函式和Qt的介面結合了

QtQLineEdit的新樣式和補全歷史記錄

一、簡介        利用背景圖片設計出QLineEdit新的樣式,起到美化介面的效果,並增加自動補全歷史記錄的功能,就可以作為一個完整的庫。  二、詳解 1、知識點 (1)切換QLineEdit的背景 void InnerLineEdit::setNormal()

Qtlog除錯日誌

一、簡介       最近因除錯code時,想了解程式的流程,但苦於沒有一個簡易的日誌記錄,不停使用qDebug列印輸出,而最終提交程式碼時得去多次刪除列印資訊,有時還會出現新修改的程式碼分不清是哪些部分。而使用#ifdef _DEBUG又比較煩這套,因此寫了些簡單的日誌

UART串列埠通訊()--基礎概述

通訊按照傳統的理解就是資訊的傳輸與交換。UART(Universal Asynchronous Receiver/Transmitter,即通用非同步收發器)序列通訊是微控制器最常用的一種通訊技術,通常用於微控制器和電腦之間以及微控制器和微控制器之間的通訊。 以下我們以STC98C52微控制器為

core學習歷程五 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計解析:簡單日誌記錄 + 服務切面快取 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定義篩選,Redis入門 11.1

繼續學習 “老張的哲學”博主的系列教程,感謝大神們的無私分享 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 說是朦朧,,emmm,對我來說是迷糊哈。上半段正常,下半段有點難理解,操作是沒問題。多看幾遍再消

Qt八視窗下方彈出提示資訊

一、簡介       在專案中一般都會彈出新的子對話方塊顯示提示資訊,但對於一些因後臺資料變化引發的提示還是在視窗下方彈出提示資訊比較合理。點選按鈕彈出提示資訊,當滑鼠放在提示資訊對話方塊上時,暫停動畫可長時間檢視提示資訊。 二、詳解 1、程式碼 (1)fader

Qt二二維碼條形碼解析

一、簡介         二維條碼/二維碼(2-dimensional bar code)是用某種特定的幾何圖形按一定規律在平面(二維方向上)分佈的黑白相間的圖形記錄資料符號資訊的,其應用廣泛,如:產品防偽/溯源、廣告推送、網站連結、資料下載、商品交易、定位/導航、電子憑

【OpenCV入門教程】 形態學影象處理(二):開運算閉運算形態學梯度頂帽黑帽合輯

上篇文章中,我們重點了解了腐蝕和膨脹這兩種最基本的形態學操作,而運用這兩個基本操作,我們可以實現更高階的形態學變換。所以,本文的主角是OpenCV中的morphologyEx函式,它利用基本的膨脹和腐蝕技術,來執行更加高階的形態學變換,如開閉運算、形態學梯度、“頂帽”、“黑帽

Python例項四遞迴求斐波那契階乘累加和

一、問題 指令碼遞迴求斐波那契、階乘和、累加和函式的執行。先在單執行緒中執行這三個函式,然後在多執行緒中做同樣的事,以說明多執行緒的好處。以及子類化threading執行緒模組的Thread類,靈活地來自定義執行緒物件。 二、解決 1、程式碼 #!/usr/bin/

shell例項九格式化輸出大數字

一、問題       格式化輸出大數字,使得輸出結果更清晰地看出數字的數量級。預設用逗號(可用-d指定整數的分隔符)分隔整數部分,用點號(可用-t指定整數與小數的分隔符)分隔整數與小數部分。如1123456789.012輸出為1,123,456,789.012。 二、詳

【REACT NATIVE 系列教程】外掛的安裝使用與更新(示例:REACT-NATIVE-TAB-NAVIGATOR)

本篇主要來詳細介紹如何安裝、升級外掛及講解一個react-native-tab-navigator的示例。本文舉例使用的外掛:react-native-tab-navigator ,選項卡形式的導航1. 通過  https://www.npmjs.com 找到我們想使用的外掛, 搜尋:react-native

Qt介面自定義

一、簡介       Qt自帶的介面不利於樣式的調整和美化,自定義介面便於設計風格。 二、詳解 1、程式碼 (1)pagenumbercontrol.h #ifndef PAGENUMBERCONTROL_H #define PAGENUMBERCONTROL_H