awkには、連想配列として配列が用意されていますが、pythonやperlのように配列操作が充実してないですよね。

特に、unshift・shift・push・pop関数に関しては、あるとほんと便利なので、自作して使いまわしています。

下記に紹介してみたいと思います(あくまで自作なので、本来のunshift・shift・push・pop関数と異なる場合があるのはご了承ください)。

スポンサーリンク

サンプルコード

※awkの使い方をまとめて一覧にしました。
参考:awk入門-使い方まとめ一覧-

unshift・shift・push・pop関数を、それぞれユーザー定義関数としてunshiftArr()・shiftArr()・pushArr()・popArr()を定義しています。in.txtを一行ずつ読み込んで、unshiftArr()をcallして1フィールド(列)目を配列の先頭に詰めていきます。その後、ENDブロックで、unshiftArr()・shiftArr()・pushArr()・popArr()を順に実行しています。

例えば、下記のin.txtがあったとします。

 $ cat in.txt 
e
f
g
h
i

下記がサンプルコードになります。
 $ cat sample.awk 
#!/bin/sh
cat in.txt | awk '		
	{
		unshiftArr(arrF1, $1)
	}
	END{
		print ""
		print "unshift操作"
		unshiftArr(arrF1, "2")

		print ""
		print "shift操作"
		shiftArr(arrF1)

		print ""
		print "push操作"
		pushArr(arrF1, "2")
		
		print ""
		print "pop操作"
		popArr(arrF1)
		popArr(arrF1)
		popArr(arrF1)
		popArr(arrF1)
		popArr(arrF1)
		popArr(arrF1)
		popArr(arrF1)

		delete arrF1
				
		print ""
		print "unshift操作"
		unshiftArr(arrF2, 3)

		print "unshift操作"
		shiftArr(arrF2)
		shiftArr(arrF2)
		delete arrF2
	}
	#print関数
	function printArr(arr) {
		if(length(arr) == 0){
			print "Empty"
			return
		}
		for (i = 0; i < length(arr); i++ ) {
			printf "%s," , arr[ i ]
		}
		print ""
	}
	#unshift関数
	function unshiftArr(arr, inStr ) {
		for(i = length(arr); i > 0 ; i-- ) {
			arr[ i ] = arr[ i - 1 ]
		}
		arr[ 0 ] = inStr #index=0にinStrを入力

		printArr(arr)
	}
	#shift関数
	function shiftArr(arr) {
		if(length(arr) == 0){
			print "Empty"
			return
		}
		for(i = 0; i < length(arr) - 1 ; i++ ) {
			arr[ i ] = arr[ i + 1 ]
		}
		delete arr[ length(arr) - 1 ]
		
		printArr(arr)
	}
	#push関数
	function pushArr(arr, inStr ) {
		arr[ length(arr) ] = inStr
			
		printArr(arr)
	}
	#pop操作
	function popArr(arr) {
		if(length(arr) == 0){
			print "Empty"
			return
		}
		delete arr[ length(arr) - 1]
		
		printArr(arr)
	}
'

下記が実行結果になります。
 $ ./sample.awk 
e,
f,e,
g,f,e,
h,g,f,e,
i,h,g,f,e,

unshift操作
2,i,h,g,f,e,

shift操作
i,h,g,f,e,

push操作
i,h,g,f,e,2,

pop操作
i,h,g,f,e,
i,h,g,f,
i,h,g,
i,h,
i,
Empty
Empty

unshift操作
3,
unshift操作
Empty
Empty

スポンサーリンク

awkでunshift関数を自作

unshiftについては下記のようにユーザー定義しています。
実行すると、配列arrの先頭に、文字列instrを入力します。

	#unshift関数
	function unshiftArr(arr, inStr ) {
		for(i = length(arr); i > 0 ; i-- ) {
			arr[ i ] = arr[ i - 1 ]
		}
		arr[ 0 ] = inStr #index=0にinStrを入力

		printArr(arr)
	}

awkでshift関数を自作

shiftについては下記のようにユーザー定義しています。
実行すると、配列arrの先頭が削除されます。

	#shift関数
	function shiftArr(arr) {
		if(length(arr) == 0){
			print "Empty"
			return
		}
		for(i = 0; i < length(arr) - 1 ; i++ ) {
			arr[ i ] = arr[ i + 1 ]
		}
		delete arr[ length(arr) - 1 ]
		
		printArr(arr)
	}

awkでpush関数を自作

pushについては下記のようにユーザー定義しています。
実行すると、配列arrの後尾にinStrが入力されます。

	#push関数
	function pushArr(arr, inStr ) {
		arr[ length(arr) ] = inStr
			
		printArr(arr)
	}

awkでpop関数を自作

popについては下記のようにユーザー定義しています。
実行すると、配列arrの後尾が削除されます。

**
空の配列を引数にしたときの挙動について、ご指摘を頂きました。
下記のように、空の場合はreturnするようにして変更いたしました。
引数に設定した時点で空の配列が生成されてしまいますが、生成した配列のdeleteは読び出し側の責務で行うようにと考えました。
また、pop時に値を返していませんが、これは自作した時に必要がなかったので、あえて返していないのが実情です。
本記事の趣旨は自作の関数の紹介なのでこのままにさせてください。
一連のご指摘を頂きました読者様ありがとうございました。

 	#pop操作
	function popArr(arr) {
		if(length(arr) == 0){
			print "Empty"
			return
		}
		delete arr[ length(arr) - 1]
		
		printArr(arr)
	}

スポンサーリンク