siwen

siwen

😉

awk プログラミング

awk プログラミング#

awk 演算子#

算術演算子#

演算子説明
+ - * / %足し算 引き算 掛け算 割り算 余り
^ **累乗
++ --インクリメント デクリメント (前置または後置として使用可能)

代入演算子#

演算子説明
= += -= *= /= %= ^= **=代入文(a+=b は a=a+b と等価、他も同様)

関係演算子#

演算子説明
> < >= <= != ==比較文(成立時は真を返し、成立しない時は偽を返す)

論理演算子#

演算子説明
||論理和(真があれば真)
&&論理積(偽があれば偽)
!論理否定(真は偽に、偽は真に)

正規表現演算子#

演算子説明
~正規表現にマッチ
!~正規表現にマッチしない

その他の演算子#

演算子説明
$フィールド参照
空白文字列結合子
in配列メンバーの反復子(通常は for ループと共に使用し、配列を走査するため)
? :三項演算子(C 言語と同様: 式 ? 文1 : 文2 式が成立すれば文 1 を実行し、そうでなければ文 2 を実行)

awk フロー制御文#

条件判断文#

# if
if()

	
# if-else
if()
	文1
else
	文2 
	
# if-else-if
if()
	文1 
else if (式2)
	文2 
else
	文3 

awk の分岐構造はネストを許可しており、判断と読みやすさを向上させるために、複数の文を {} で括ることができます。

ループ文#

  • 三大ループ文
# whileループ
while(){

}

# forループ
# フォーマット1
for(初期変数;ループ判断文;ループ反復増加/減少文){

}

# フォーマット2 
for(変数 in 配列){

}

# do-whileループ
do{

} while(条件)

ループフローを変更する文:

  • break; ループを終了
  • continue; 今回のループをスキップ
  • exit status_code; exit 文はスクリプトの実行を停止するために使用されます(END があれば END に移行)、整数パラメータを受け取り、awk プロセスの終了ステータスコードとして使用されます。パラメータが提供されない場合、デフォルトは 0 です( $? で確認できます)。

awk 配列#

配列は awk の魂であり、テキスト処理では配列処理がよく使用されます。

awk 配列の特性:

  • awk 配列のインデックスは数字でも文字列でも可能であるため、awk の配列は連想配列です。
  • 内部的に、awk 配列のインデックスはすべて文字列であり、数値インデックスも使用時に内部で文字列に変換されます。
  • awk の配列要素の順序は、要素挿入時の順序と必ずしも一致しません。
  • awk の配列は事前に宣言する必要はなく、サイズを宣言する必要もありません。
  • 配列要素は文脈に応じて 0 または空文字列で初期化されます。

配列の作成(追加、変更)#

構文:配列名[インデックス] = 値

  • 配列に要素を追加 / 変更する構文は、配列を作成するのと同じです。

配列要素へのアクセス#

構文:配列名[インデックス]

配列要素の削除#

構文:delete 配列名[インデックス]

  • 存在しない要素を削除してもエラーは発生しません。
  • delete 配列名 は配列のすべての要素を直接削除できます。

配列関連関数#

  • length(arr) 配列の長さを取得

  • asort(arr) 配列をソートし、配列の長さを返す

  • split(str,arr,sep) 文字列を配列に分割し、配列の長さを返す

    生成された awk 配列のインデックスは 1 から始まり、C 言語の配列とは異なります。

[root@localhost ~]# awk 'BEGIN{str="a,b,c,d";len=split(str,arr,",");print len,length(arr),asort(arr),arr[1]}'
4 4 4 a

配列の反復#

# 方法1
[root@localhost ~]# awk 'BEGIN{
str="a,b,c,d";
len=split(str,arr,",");
for(i in arr){
print i,arr[i];
}
}'
1 a
2 b
3 c
4 d

# 方法2 (awk配列は連想配列であり、この方法は順序付きの反復を保証します)
[root@localhost ~]# awk 'BEGIN{
str="a,b,c,d";
len=split(str,arr,",");
for(i=1;i<=len;i++){
print i,arr[i];
}
}'
1 a
2 b
3 c
4 d

# 配列に特定のキーが含まれているかどうかを判断
if(key in arr)

# arrが配列かどうかを検出
isarray(arr)  arrが配列であれば1を返し、そうでなければ0を返す
typeof(arr)   データ型を返し、arrが配列であれば 'array' を返す

多次元配列#

  • awk は一次元配列のみをサポートしており、一次元配列を使用して多次元配列をシミュレートできます。
# 次のような3*3の二次元配列arr:
1 2 3 
4 5 6
7 8 9
C言語では、arr[0][0] = 100;awkでは、arr[0,0] = 100と設定できます。これにより、arr[0,1]、arr[0,2]...arr[3,3]となります。
実際には、0,1   0,2   3,3   は単なる文字列インデックスです。

awk 組み込み関数#

数学関数#

関数説明
sin(expr)expr の正弦値を返す
cos(expr)expr の余弦値を返す
atan2(y,x)y/x の逆正接値を返す
log(expr)expr の自然対数を返す
exp(expr)底 e の expr の指数値を返す
sqrt(expr)expr の平方根を返す
int(expr)expr を整数に切り捨てた値を返す
rand()任意の数字 n を返す、0<=n<1
srand([expr])rand 関数のシード値を expr パラメータの値に設定します。パラメータを省略すると、ある日の時間を使用します。

#

# 0-99の間のランダム整数を取得
[root@localhost ~]# awk 'BEGIN{srand();randint=int(100*rand());print randint}'

文字列関数#

関数説明
asort(arr [, d ])ASCII 文字順に配列 arr の値をソート
asorti(arr [, d])ASCII 文字順に配列 arr のキーをソート
gsub(regexp, sub, str)文字列内で指定されたパターンにマッチするすべての文字列を検索し、見つかったものを別の文字列に置き換える
sub(search, sub, str)文字列内で指定された文字列を検索し、見つかった場合は別の文字列に置き換える。1 回だけ置き換えます
index(str, sub)ある文字列が別の文字列内にある位置を検索します。見つかればその位置を返し、見つからなければ 0 を返します
length(str)文字列の長さを返す
match(str, regexp)マッチするパターンの最初の最長部分文字列の位置を検索します。見つからなければ 0 を返し、見つかれば最長部分文字列の開始位置を返します
split(str, arr, regexp)文字列を指定されたパターンに基づいて複数の部分文字列に分割します。パターンを渡さない場合は、変数 FS の値を使用します
printf(format, expr-list)指定された文字列フォーマットと渡された変数に基づいて文字列を構築し、標準出力に出力します
strtonum(str)文字列が数字かどうかをチェックし、それを 10 進数に変換します
substr(str, start, len)文字列 strstart の位置から始まり、長さが len の部分文字列を返します
tolower(str)指定された文字列内の大文字を小文字に変換します
toupper(str)指定された文字列内の小文字を大文字に変換します

#

# asort(arr[,d])  arr-->配列 d-->配列。もしこのパラメータを渡すと、arrは変更されず、arrのすべての要素がdにコピーされ、dがソートされます。
[root@localhost ~]# awk 'BEGIN{
    arr[11]=800;
    arr[22]=200;
    arr[33]=300;
    arr[44]=100;
	for(i in arr){
        print i,arr[i];
    }
    asort(arr);
    print;
    for(j in arr){
        print j,arr[j];
    }
}'
11 800
22 200
33 300
44 100

1 100
2 200
3 300
4 800

# asorti
[root@localhost ~]# awk 'BEGIN{
	arr[11]=800;
	arr[22]=200;
	arr[33]=300;
	arr[44]=100;
    for(i in arr){
        print i,arr[i];
    }
    asorti(arr);
    print;
    for(j in arr){
        print j,arr[j];
    }
}'
11 800
22 200
33 300
44 100

1 11
2 22
3 33
4 44

# gsub(regexp, sub, str)
[root@localhost ~]# awk 'BEGIN{
    str="hello world";
    gsub("[o|l]","*",str);
    print str;
}'
he*** w*r*d

# sub(search, sub, str)
[root@localhost ~]# awk 'BEGIN{
    str="hello world";
    sub("[o|l]","*",str);
    print str;
}'
he*lo world

# index(str, sub)
[root@localhost ~]# awk 'BEGIN{
    str="hello world";
    idx=index(str,"l");
    print idx;
}'
3

# match(str, regexp)
[root@localhost ~]# awk 'BEGIN{
    str="hello world hi haaaaaa";
    idx=match(str,"h*");
    print idx;
}'
1

# strtonum(str)
[root@localhost ~]# awk 'BEGIN{
    str="01010";
    res=strtonum(str);
    print res;
}'
520

# substr(str, start, len)
[root@localhost ~]# awk 'BEGIN{
    str="hello world";
    res=substr(str,7,5);
    print res;
}'
world

# tolower(str)
[root@localhost ~]#  awk 'BEGIN{
    str="HAHAHA";
    res=tolower(str);
    print res;
}'
hahaha

# tolupper(str)
[root@localhost ~]# awk 'BEGIN{
    str="hello world";
    res=toupper(str);
    print res;
}'
HELLO WORLD

日付と時間の関数#

関数説明
systime()現在のタイムスタンプを返す
mktime(datespec)指定された形式の時間文字列(YYYY MM DD HH MM SS)をタイムスタンプに変換します
strftime([format [, timestamp]])タイムスタンプ形式の時間を指定された時間フォーマットに基づいて文字列形式で表現します

#

# systime()
[root@localhost ~]# awk 'BEGIN{print systime()}'
1672448348

# mktime(datespec)
[root@localhost ~]# awk 'BEGIN{print mktime("2022 12 31 09 00 00")}'
1672448400

# strftime([format [, timestamp]])
[root@localhost ~]# awk 'BEGIN{print strftime("%c",systime())}'
Sat Dec 31 09:03:53 2022

フォーマット#

フォーマット記号説明
%aローカライズされた曜日、例えば 木曜日
%Aローカライズされた曜日の略称、例えば
%bローカライズされた月の名前、例えば 5月
%Bローカライズされた月、例えば 5月
%cC 言語の %A %B %d %T %Y の形式、例えば 2019年05月30日 木曜日 21時08分37秒
%C本年度の世紀部分。つまり、4 桁の年の最初の 2 桁、例えば 2019 年の 20
%d当月の何日か、範囲は 01-31、例えば 30
%Dフォーマット %m/%d/%y の略称、例えば 05/30/19
%e当月の何日か、範囲は 1-31、10 未満の場合は前に空白を補う、例えば 11 に補完
%FISO 8601 日付形式の %Y-%m-%d の別名
%gISO 8601 日付形式の週番号を 100 で割った値、範囲 00-99 例えば 1993 年 1 月 1 日は 1992 年の第 53 週
%GISO 週番号制の完全な年、4 桁の年のように、例えば 2019
%hフォーマット %b の別名
%H24 時間制の現在の時間の時、範囲は 00–23
%I12 時間制の現在の時間の時、範囲は 01–12
%j一年の何日か、範囲は 001–366
%m現在の時間の月、範囲は 01–12
%M現在の時間の分、範囲は 00–59
%n改行文字 \n
%pローカライズされた 12 時間制の時間形式の AM または PM、つまりローカライズされた午前または午後の表現
%rローカライズされた 12 時間制の時間形式、C 言語の %I:%M:%S %p に似ています
%Rフォーマット %H:%M の略称
%S現在の時間の秒、範囲は 00-6060 は主にうるう秒を考慮しています
%tタブ文字 \t
%Tフォーマット %H:%M:%S の略称
%u一週間の何日か、つまり曜日、範囲は 1–7。週は月曜日から始まります
%U一年の何週か、範囲は 00-53。最初の週は最初の日曜日から始まります
%V一年の何週か、範囲は 01-53。最初の週は最初の月曜日から始まります
%w一週間の何日か、つまり曜日、範囲は 0–6。週は日曜日から始まります
%W一年の何週か、範囲は 00-53。最初の週は最初の月曜日から始まります
%xローカライズされた完全な日付表示、例えば %A %B %d %Y、例えば 木曜日 5月 30 2019
%Xローカライズされた完全な時間表示、C 言語の %T に似ています、例えば 07:06:05
%y2 桁の 10 進年、つまり年の後の 2 桁を取得、範囲は 00-99、例えば 201919 を返します
%Y完全な 4 桁の 10 進年、例えば 2019
%z+HHMM 形式のタイムゾーンオフセット。これは RFC 822 または RFC 1036 日付形式の一部です。
%Zタイムゾーン名またはタイムゾーン名の略称。タイムゾーンがない場合は空文字列 '' を返します。

その他の関数#

関数説明
close(expr)既に開いているファイルまたはパイプを閉じるために使用します。
system(command)システムスクリプトコマンドを実行し、スクリプトの実行の終了ステータスを返します。
getline次の行を読み取ります。
next次の行を処理します。
nextfile次のファイルを処理します。

#

# close(expr) 
[root@localhost ~]# awk 'BEGIN{while("cat emp.txt" | getline){print $0}close("emp.txt")}'

# system(command)
[root@localhost ~]# awk 'BEGIN{system("ls -l")}'

# getline
[root@localhost ~]# awk '{getline;print}' emp.txt
002 李四 2000 10
004 赵六 2000 20
006 小丽 800 20

[root@localhost ~]# awk 'BEGIN{print "入力:";getline name;print name}'
入力:
123
123

# next
[root@localhost ~]# awk '{if($3<2000)next;print}' emp.txt
002 李四 2000 10
003 王五 3000 10
004 赵六 2000 20

# nextfile
[root@localhost ~]# awk '{if($3==2000) nextfile;print}' emp.txt file
001 张三 1000 10
xxx is a hanhan. ^_^

are you kidding?
I think ...
My phone number is 1872272****.

カスタム関数#

  • 関数定義
function 関数名(引数1, 引数2, ...) { 
   関数本体
}
  • 関数名は文字で始まる必要があり、文字、数字、アンダースコアで構成できます。予約語は使用できません。
  • 関数本体の文はセミコロンで区切る必要があります。
  • 関数は戻り値を持つことも、持たないこともできます。戻り値が必要な場合は、大括弧内で return キーワードを使用する必要があります。
  • 関数呼び出し
# 引数なしの関数を呼び出す
fun_name 
# 引数ありの関数を呼び出す
fun_name(arg1[,arg2...])
# 戻り値のある関数を呼び出す
var = fun_name([arg1...])

関数は BEGIN本体, END の中で呼び出すことができます。

#

# 引数なしの関数
[root@localhost ~]# awk 'BEGIN{
	fun1()
}
function fun1(){
	print "これは関数です!"
}'
これは関数です!

# 引数ありの関数
[root@localhost ~]# awk 'BEGIN{
	fun2(10,20)
}
function fun2(num1,num2){
	print "関数の実行結果は:"num1+num2
}'
関数の実行結果は:30

# 戻り値のある関数
[root@localhost ~]# awk 'BEGIN{
	res = fun3(10,20);
	print "num1+num2の和は:"res
}
function fun3(num1,num2){
	return num1+num2
}'
num1+num2の和は:30
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。