散仙学shellとプログラミングする(十二)
詳細
前の文章は散仙がsedの進級について書いたが、本編ではlinuxの中でもう一つの非常に強力なテキスト処理言語gawkを見て、gawkに関する基礎があり、散仙は前の2つの文章で、紹介もあり、よく知らない友达もいて、もう一度振り返ることができる.
gawkは豊富なプログラミング言語で、高度なプログラムを書くことでデータを処理することができます.私たちが他のプログラミング言語の経験があれば、死んだJAVA、C#、Python、shell、javascriptにかかわらず、gawkを手に入れるのはとても親切で簡単です.
次にgawkの中の変数を見てみましょう.gawkの中には全部で2つの異なる変数があります.1つ目は自己変数で、2つ目はカスタム変数です.次に、具体的ないくつかのよく使われる変数を見てみましょう.
シーケンス番号
gawk固有変数名
説明
1
FIELDWIDTS
各データフィールドの正確な幅を定義するスペースで区切られた列の数
2
FS
フィールド区切り文字の出力
3
RS
入力データの行区切り
4
OFS
フィールド区切り文字の出力
5
ORS
出力データ行区切り
変数FSおよびOFSは、gawkがデータストリームのデータフィールドをどのように処理するかを定義し、デフォルトではgawkはOFSをスペースに設定します.
出力フィールドの区切り:
FIELDWIDTHSB変数は固定桁数で区切られますが、長くなるフィールドには適していません.
行区切り記号の使用方法を次に示します.
次のフローを分析すると、上記の例ではFSの区切り記号を改行記号に設定します.これはgawkが行全体をフィールドとして、行区切り記号をスペースに設定し、データ行間に空白の行を残し、gawkが空白の行を区切り記号として使用することを示しています.
上のセパレータ変数のほかに、gawkには他の変数があります.
ARGC現在のコマンドライン数
ARGIND現在のファイルはARGVの中の位置
ARGVコマンドラインパラメータを含む配列
FNR現在のデータファイルのデータ行数
NFデータファイル内のフィールド総数
ARG変数は、gawkコマンドとccパラメータを含むコマンドラインに2つのパラメータがあることを示し、最初の配列値はgawkコマンド後の最初のコマンドラインパラメータである
ENVIRONコマンドはSHELLの変数から値を抽出できますが、インデックスではなく文字列を使用して識別されます.
NF変数では、データ行の最後のフィールドを指定できます.どのくらいのフィールドがあるかを知る必要はありません.
FNR変数は、現在処理されているデータ行の合計数を含み、NR変数は、すべての合計数を含む
次にgawkでカスタム変数を使用する方法を示します.
すでに使用されている変数は再使用できます.
gawkで算術式を使うこともできます
コマンド側でパラメータを出力することもできます.
BEGINの前に定義した変数であれば解析できないかもしれませんが、-vパラメータを追加する必要があります.
gawkでは配列変数も簡単に使用できます.
配列を巡るには、私たちが最もよく知っているforeachの方法もあります.
配列変数を削除するにはdeleteコマンドを使用します.
正規表現をgawkと組み合わせる方法
一致オペレータを次に示します.
$n~は、カラム内でクエリーフィルタリングを指定できます.
!番号はソートできます.正規のフィルタ:
数式:
テキストを比較することもできます.
次はgawkの構造化プログラミングを見てみましょう.
if-elseの例を見てみましょう.
次にwhile文を見てみましょう.
gawkはwhileでbreakとcontinueキーワードを使用することをサポートします.
for文を見てみましょう.
使いやすい
gawkは出力printfコマンドのフォーマットもサポート
gawkでは、一般的な組み込み関数もサポートされています.
cos(x)コサイン
log(x)対数
rand()が0より大きく1より小さいランダム浮動小数点値
他にも文字列関数があり、他のプログラミングの基礎を持っている人は、次の関数を簡単に見ることができます.
length(s)文字列長をとる
split()ある記号で分割
asort()ソート
match()マッチングサブ列
tolower()小文字
toupper()大文字に変換
など
時間関数を見てみましょう.
mktime(datespec)YYY-MM-DD HHHMMSS形式で変換する時間が間違っている
strftime(format,[timestamp])フォーマット日
Systime()は現在のタイムスタンプを返します
カスタム関数を次に示します.
関数名が一意であることに注意してください.
最後にgawkで関数ライブラリをカスタマイズする方法を見てみましょう.
shell端末でライブラリ関数を直接使用することはできませんが、複数の-fコマンドで複数のファイルを実行できます.
前の文章は散仙がsedの進級について書いたが、本編ではlinuxの中でもう一つの非常に強力なテキスト処理言語gawkを見て、gawkに関する基礎があり、散仙は前の2つの文章で、紹介もあり、よく知らない友达もいて、もう一度振り返ることができる.
gawkは豊富なプログラミング言語で、高度なプログラムを書くことでデータを処理することができます.私たちが他のプログラミング言語の経験があれば、死んだJAVA、C#、Python、shell、javascriptにかかわらず、gawkを手に入れるのはとても親切で簡単です.
次にgawkの中の変数を見てみましょう.gawkの中には全部で2つの異なる変数があります.1つ目は自己変数で、2つ目はカスタム変数です.次に、具体的ないくつかのよく使われる変数を見てみましょう.
シーケンス番号
gawk固有変数名
説明
1
FIELDWIDTS
各データフィールドの正確な幅を定義するスペースで区切られた列の数
2
FS
フィールド区切り文字の出力
3
RS
入力データの行区切り
4
OFS
フィールド区切り文字の出力
5
ORS
出力データ行区切り
変数FSおよびOFSは、gawkがデータストリームのデータフィールドをどのように処理するかを定義し、デフォルトではgawkはOFSをスペースに設定します.
[search@h1 822]$ gawk '{print $1,$2,$3}' b.txt
a b c
solr hadoop lucene
[search@h1 822]$ cat b.txt
a b c
solr hadoop lucene
[search@h1 822]$ gawk '{print $1,$2,$3}' b.txt
a b c
solr hadoop lucene
[search@h1 822]$ gawk '{print $1,$2}' b.txt
a b
solr hadoop
[search@h1 822]$
出力フィールドの区切り:
[search@h1 822]$ cat b.txt
a b c
solr hadoop lucene
[search@h1 822]$ gawk 'BEGIN{FS=" ";OFS="-"} {print $1,$2,$3 }' b.txt
a-b-c
solr-hadoop-lucene
[search@h1 822]$ gawk 'BEGIN{FS=" ";OFS="--"} {print $1,$2,$3 }' b.txt
a--b--c
solr--hadoop--lucene
[search@h1 822]$ gawk 'BEGIN{FS=" ";OFS="-->"} {print $1,$2,$3 }' b.txt
a-->b-->c
solr-->hadoop-->lucene
[search@h1 822]$
FIELDWIDTHSB変数は固定桁数で区切られますが、長くなるフィールドには適していません.
[search@h1 822]$ cat c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ gawk 'BEGIN{FIELDWIDTHS="2 3 2"}{print $1,$2,$3}' c.txt
10 034 55
12 345 22
22 222 22
56 788 90
[search@h1 822]$
行区切り記号の使用方法を次に示します.
[search@h1 822]$ cat cc
1
2522252
2
2522252
3
2522252
[search@h1 822]$ gawk 'BEGIN{FS="
"; RS=""} {print $1,$2}' cc
1 2522252
2 2522252
3 2522252
[search@h1 822]$
次のフローを分析すると、上記の例ではFSの区切り記号を改行記号に設定します.これはgawkが行全体をフィールドとして、行区切り記号をスペースに設定し、データ行間に空白の行を残し、gawkが空白の行を区切り記号として使用することを示しています.
上のセパレータ変数のほかに、gawkには他の変数があります.
ARGC現在のコマンドライン数
ARGIND現在のファイルはARGVの中の位置
ARGVコマンドラインパラメータを含む配列
FNR現在のデータファイルのデータ行数
NFデータファイル内のフィールド総数
[search@h1 822]$ gawk 'BEGIN{print ARGC,ARGV[1]}' cc
2 cc
[search@h1 822]$
ARG変数は、gawkコマンドとccパラメータを含むコマンドラインに2つのパラメータがあることを示し、最初の配列値はgawkコマンド後の最初のコマンドラインパラメータである
[search@h1 822]$ gawk 'BEGIN{print ENVIRON["HOME"] ; print ENVIRON["PATH"] } '
/home/search
.:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/jdk/bin:/home/search/hadoop/bin:/home/search/hadoop/sbin:/usr/local/ant/bin:/usr/local/maven/bin:/home/search/hive/bin:/home/search/hive/conf:/home/search/bin
[search@h1 822]$
ENVIRONコマンドはSHELLの変数から値を抽出できますが、インデックスではなく文字列を使用して識別されます.
[search@h1 822]$ gawk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}' /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
shutdown:/sbin/shutdown
halt:/sbin/halt
mail:/sbin/nologin
uucp:/sbin/nologin
operator:/sbin/nologin
games:/sbin/nologin
gopher:/sbin/nologin
ftp:/sbin/nologin
nobody:/sbin/nologin
vcsa:/sbin/nologin
saslauth:/sbin/nologin
postfix:/sbin/nologin
sshd:/sbin/nologin
mysql:/bin/bash
search:/bin/bash
[search@h1 822]$
NF変数では、データ行の最後のフィールドを指定できます.どのくらいのフィールドがあるかを知る必要はありません.
[search@h1 822]$ cat c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ gawk 'BEGIN{FS=","} {print $1, "FNR="FNR}' c.txt
1003455 FNR=1
1234522 FNR=2
2222222 FNR=3
5678890 FNR=4
[search@h1 822]$
FNR変数は、現在処理されているデータ行の合計数を含み、NR変数は、すべての合計数を含む
[search@h1 822]$ cat c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ gawk 'BEGIN{FS=","} {print $1, "FNR="FNR}' c.txt
1003455 FNR=1
1234522 FNR=2
2222222 FNR=3
5678890 FNR=4
[search@h1 822]$ gawk 'BEGIN{FS=","} {print $1, "FNR="FNR, "NR="NR}' c.txt
1003455 FNR=1 NR=1
1234522 FNR=2 NR=2
2222222 FNR=3 NR=3
5678890 FNR=4 NR=4
[search@h1 822]$ gawk 'BEGIN{FS=","} {print $1, "FNR="FNR, "NR="NR}' c.txt c.txt
1003455 FNR=1 NR=1
1234522 FNR=2 NR=2
2222222 FNR=3 NR=3
5678890 FNR=4 NR=4
1003455 FNR=1 NR=5
1234522 FNR=2 NR=6
2222222 FNR=3 NR=7
5678890 FNR=4 NR=8
[search@h1 822]$
次にgawkでカスタム変数を使用する方法を示します.
[search@h1 822]$ gawk 'BEGIN{test=" , "; print test}'
,
[search@h1 822]$
[search@h1 822]$ gawk 'BEGIN{test=" , "; print test ; test=123; print test}'
,
123
[search@h1 822]$
すでに使用されている変数は再使用できます.
gawkで算術式を使うこともできます
[search@h1 822]$ gawk 'BEGIN{x=4; x=x * 2 + 3 ; print x}'
11
[search@h1 822]$
コマンド側でパラメータを出力することもできます.
[search@h1 822]$ cat c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ gawk -f script n=1 c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ cat script
BEGIN{FS=","}
{print $n}
[search@h1 822]$
[search@h1 822]$ gawk -f s2 n=1 c.txt
:
1003455
1234522
2222222
5678890
[search@h1 822]$ cat c.txt
1003455
1234522
2222222
5678890
[search@h1 822]$ cat s2
BEGIN{ print " : "; n; FS="."}
{ print $n }
[search@h1 822]$
BEGINの前に定義した変数であれば解析できないかもしれませんが、-vパラメータを追加する必要があります.
gawkでは配列変数も簡単に使用できます.
[search@h1 822]$ gawk 'BEGIN{ a["key"]="value" ; print a["key"]}'
value
[search@h1 822]$
配列を巡るには、私たちが最もよく知っているforeachの方法もあります.
[search@h1 822]$ gawk 'BEGIN{ a["1"]="aa"; a["2"]="ab" ; a["3"]="ac" ; for (t in a){ print " : ",t," : ", a[t] } }'
: 1 : aa
: 2 : ab
: 3 : ac
[search@h1 822]$
配列変数を削除するにはdeleteコマンドを使用します.
[search@h1 822]$ gawk 'BEGIN{ a["1"]="aa"; a["2"]="ab" ; a["3"]="ac" ; delete a["2"] ; for (t in a){ print " : ",t," : ", a[t] } }'
: 1 : aa
: 3 : ac
[search@h1 822]$
正規表現をgawkと組み合わせる方法
[search@h1 822]$ cat a.txt
data11
data22
data111
data4561
[search@h1 822]$ gawk 'BEGIN{FS=","} /11/{print $1} ' a.txt
data11
data111
[search@h1 822]$
一致オペレータを次に示します.
[search@h1 822]$ cat a.txt
data11 test11 bbb111
data22 kkk222 ccc222
data111 ggg jjjj
data4561 111 3333
[search@h1 822]$ gawk 'BEGIN{FS=" "} $2 ~ /^kk/{ print $0 }' a.txt
data22 kkk222 ccc222
[search@h1 822]$ gawk 'BEGIN{FS=" "} $1 ~ /1/{ print $0 }' a.txt
data11 test11 bbb111
data111 ggg jjjj
data4561 111 3333
[search@h1 822]$ gawk 'BEGIN{FS=" "} $1 ~ /^1/{ print $0 }' a.txt
[search@h1 822]$ gawk 'BEGIN{FS=" "} $1 ~ /^11/{ print $0 }' a.txt
[search@h1 822]$ gawk 'BEGIN{FS=" "} $1 ~ /11/{ print $0 }' a.txt
data11 test11 bbb111
data111 ggg jjjj
[search@h1 822]$
$n~は、カラム内でクエリーフィルタリングを指定できます.
!番号はソートできます.正規のフィルタ:
[search@h1 822]$ cat a.txt
data11 test11 bbb111
data22 kkk222 ccc222
data111 ggg jjjj
data4561 111 3333
[search@h1 822]$ gawk 'BEGIN{FS=" "} $1 !~ /11/{ print $0 }' a.txt
data22 kkk222 ccc222
data4561 111 3333
[search@h1 822]$
数式:
[search@h1 822]$ cat x.txt
1 solr
2 lucne
3 hadoop
1 solr2`
[search@h1 822]$ gawk '$1 == 1 { print $0 }' x.txt
1 solr
1 solr2`
[search@h1 822]$
テキストを比較することもできます.
[search@h1 822]$ cat x.txt
1 solr
2 lucne
3 hadoop
1 solr2`
[search@h1 822]$ gawk '$1 == 1 { print $0 }' x.txt
1 solr
1 solr2`
[search@h1 822]$ gawk '$2 == "hadoop" { print $0 }' x.txt
3 hadoop
[search@h1 822]$
次はgawkの構造化プログラミングを見てみましょう.
[search@h1 822]$ cat d1
10
100
20
45
1
-11
[search@h1 822]$ gawk '{ if ( $1 > 10 ) print $1} ' d1
100
20
45
[search@h1 822]$
if-elseの例を見てみましょう.
[search@h1 822]$ cat d1
10
100
20
45
1
-11
[search@h1 822]$ gawk '{ if ( $1 > 10 ) print $1} ' d1
100
20
45
[search@h1 822]$ gawk '{ if ( $1 > 10 ) { print $1} else { print " 10" } } ' d1
10
100
20
45
10
10
[search@h1 822]$
次にwhile文を見てみましょう.
[search@h1 822]$ gawk 'BEGIN{ a=4; while (a<10){ a++ ; print a} }'
5
6
7
8
9
10
[search@h1 822]$
gawkはwhileでbreakとcontinueキーワードを使用することをサポートします.
[search@h1 822]$ gawk 'BEGIN{ a=4; while (a<10){ a++ ; if(a==9){ break ;} if (a==7){ continue;} print a} }'
5
6
8
[search@h1 822]$
for文を見てみましょう.
[search@h1 822]$ gawk 'BEGIN{ for(i=1;i<=10;i++) { print " :"i }}'
:1
:2
:3
:4
:5
:6
:7
:8
:9
:10
[search@h1 822]$
使いやすい
gawkは出力printfコマンドのフォーマットもサポート
gawkでは、一般的な組み込み関数もサポートされています.
cos(x)コサイン
log(x)対数
rand()が0より大きく1より小さいランダム浮動小数点値
[search@h1 822]$ gawk 'BEGIN{ x=10 * rand() ; print x}'
2.37788
他にも文字列関数があり、他のプログラミングの基礎を持っている人は、次の関数を簡単に見ることができます.
length(s)文字列長をとる
split()ある記号で分割
asort()ソート
match()マッチングサブ列
tolower()小文字
toupper()大文字に変換
など
時間関数を見てみましょう.
mktime(datespec)YYY-MM-DD HHHMMSS形式で変換する時間が間違っている
strftime(format,[timestamp])フォーマット日
Systime()は現在のタイムスタンプを返します
[search@h1 822]$ gawk 'BEGIN{ print systime()}'
1408741666
[search@h1 822]$
カスタム関数を次に示します.
[search@h1 822]$ gawk ' function m(){ print " " } BEGIN{ m(); }'
[search@h1 822]$
関数名が一意であることに注意してください.
最後にgawkで関数ライブラリをカスタマイズする方法を見てみましょう.
[search@h1 822]$ cat ak
function a(){
print " "
}
function b(i){
for( b=i;b<10;b++){
print " : "b
}
}
function c(){
print rand()
}
[search@h1 822]$ cat ax
BEGIN{ a() }
[search@h1 822]$ cat axx
BEGIN{ c(); }
[search@h1 822]$ gawk -f ak -f ax
[search@h1 822]$ gawk -f ak -f axx
0.237788
[search@h1 822]$
shell端末でライブラリ関数を直接使用することはできませんが、複数の-fコマンドで複数のファイルを実行できます.