awk.txt ブログで記事にしていたものを、少しだけ、まとめてみます。多分このスクリプトで動くと思いますが、今の時点では確認していません。dos時代に書いたものからubuntuで動かしたものもあり、様々です。あくまで参考資料としてご利用いただければと思います。日本語文字系はutf-8です。(2022.8.25 兼子) ■dosu.awk 数値データを度数分布で文字で表すものです。 データは0~100の数値とします。 ,区切りのデータが390行近くあります。列は5列 rei.dat 75,46,77,36,25 65,33,70,36,41 58,43,68,34,25 ~略 これを処理して度数分布処理するawkのscript(dosu.awk)は $2は2列目の取り出し、$1とすれば1列目です。 dosu.awk BEGIN{ FS=","; } function rep(n,s, t){ while (n-- >0) t=t s return t } {x[int($2/5)]++;} END{ max = MAXSTARS =60 print("<< データの度数分布 >>"); for (i=0;i<20;i++) if (x[i] >max) max = x[i] for (i=0;i<20;i++) y[i] = x[i]/max *MAXSTARS printf(" 0 ! %3d\n",max); printf("%s\n"," |----+----|----+----|----+----|----+----|----+----|----+----|"); for(i=0;i<=20;i++) printf("%3d以上:%3d %s\n",5*i,x[i],rep(y[i],"*")); print("\n"); } (終わり) コマンドラインでは awk -f dosu.awk rei.dat 結果は << データの度数分布 >> 0 ! 60 |----+----|----+----|----+----|----+----|----+----|----+----| 0以上: 1 * 5以上: 1 * 10以上: 4 **** 15以上: 6 ****** 20以上: 7 ******* 25以上: 20 ******************** 30以上: 27 *************************** 35以上: 29 ***************************** 40以上: 36 ************************************ 45以上: 45 ********************************************* 50以上: 40 **************************************** 55以上: 38 ************************************** 60以上: 44 ******************************************** 65以上: 36 ************************************ 70以上: 25 ************************* 75以上: 20 ******************** 80以上: 7 ******* 85以上: 6 ****** 90以上: 1 * 95以上: 1 * 100以上: 0 となります。今はこんな処理しなくても、エクセルでもっと楽にグラフ化できるでしょう。 ■wordfrq.awk ワードカウント 英文テキストの単語の出現頻度を調べます。:;{.,等はカウントしません。 # wordfreq 単語の出現度数を印字する # bin¥awk -f wordfrq.awk eigo.txtでコマンドラインで実行します # wordfreq.awkの中身です { gsub(/[.,:;!?(){}]/,"") for (i = 1; i<=NF; i++) count[$i]++ } END { for (w in count) printf("%4d %s\n", count[w], w) | "sort /r" } (終わり) 調べるeigo.txtの中身です。5: Einstein's Clock Rearrangements in atoms produce light of precise energy. Einstein discovered that light consist of particles. The energy of light-particles fixes the rate of vibration. Light can stimulate atoms to emit similar light. Stimulated emission serves in laser in laser beams and atomic clocks. Knowing how atomic clocks work is not essential for understanding relativity. They did not exist when Alvert Einstein developed his theories. But he himself discovered the two unexpected principles by which they run. In that sense Einstein was the grandparent of the atomic clock which became, half a century later, the basis of modern timekeeping. --------後半略 出力結果出現頻度の多い順に並びます(sortを掛けています) 20 of 15 the 9 light 9 a 6 and 5 in 4 energy 4 at 3 visible 3 vibrations 3 not 3 is 3 Einstein 3 atomic 2 which 2 times 2 timekeeping 2 they 2 The 以下略です。 ■sample.awk テキスト処理 sample.txtが処理するテキストの中身、そして出力した結果とコマンドラインの書き方。 # sample.awkの中身 # 空の予定を取り去り、,区切りのcsvデータとして出力します。 # 2021/08/14(Sa)までが$1でそこから4文字拾う、次に6文字目から2文字拾う、9文字目から2文字拾う、次のフィールド$2はそのまま出力せよという意味です。FSはフィールドセパレーターでここでは半角の空白です。 sample.awk BEGIN { FS = " "; } { if(length($2)>0){ print substr($1,1,4)","substr($1,6,2)","substr($1,9,2)","$2; } } (終わり) sample.txtの中身 2021/08/14(Sa) 2021/08/15(Su) 2021/08/16(Mo) 2021/08/17(Tu) 2021/08/18(We) 2021/08/19(Th) 準備会、13:30~ 2021/08/20(Fr) 2021/08/21(Sa) 2021/08/22(Su) (活動日) 2021/08/23(Mo) 2021/08/24(Tu) 2021/08/25(We) 2021/08/26(Th) 2021/08/27(Fr) 2021/08/28(Sa) 2021/08/29(Su) 「講座」第2会議室、13:30~15:30 2021/08/30(Mo) 2021/08/31(Tu) コマンドラインでのコマンド入力、ここで¥、>は半角で入力する必要あります。 C:¥awk>bin¥awk -f sample.awk sample.txt 処理する中身が多いときはtmp.txtに出力しないとエラーになる。 C:¥awk>bin¥awk -f sample.awk sample.txt >tmp.txt 出力テキストの結果(tmp.txtの中身です) 2021,08,19,準備会、13:30~ 2021,08,22,(活動日) 2021,08,29,「講座」第2会議室、13:30~15:30 $2の空行がとれて、,区切りになっているのがわかると思います。 まずは一例です。 ■yotekidasi.awk 予定を切り出すテキスト処理 ubuntuでgawkでテキスト処理をして、予定の書き込みをする方法 (ubuntuでは文字コードはutf-8で行末はLFとしてください) yotekidasi.awk # gawk -f yotekidasi.awk plan.txt #コマンドラインで行う # 予定を切り出すため用 BEGIN { FS = " "; print " << 予定表 >>;"; print " ------------------------------ "; } { print " "$1 ; print " "$2 $3 ; print "\n\n\n\n"; print " ------------------------------ "; } (終わり) 内容はまず半角スペースで区切られたファイルが元のファイルです。 この内容を書き出してから、空行を4行加えてその後に-------を入れます。 以下例をご覧ください。 元ファイル plan.txt 2011/01/10【成人の日】# 年により異なる休日 2011/03/21【春分の日】# 年により異なる休日 2011/09/23【秋分の日】# 年により異なる休日 (終) テキスト処理後のテキストファイル << 予定表 >>; ------------------------------ 2011/01/10【成人の日】# 年により異なる休日 ■csv.awk テーブルの縦横変換(入れ替え)  テーブルの縦横を次のようにしてawkで処理して入れ替える方法だ。 コマンドラインでは下のように書く gawk -f csv.awk >tmp00.csv プログラムは下のようになる。(上ではcsv.awkというファイルの中身) # フィールド第一列めはで$1表される。これから、改行せずに連続して 1行に、コンマ付きで出力する。もしも入力ファイルがタブ区切りの時は "\t"とし、コンマ区切りの時は","とする。これだとスペース区切りでも 可能、第2列は$2に書き換えて、上のコマンドを実行する。 こうして、必要なだけ、続ける。 (FSはフィールドセパレーター、OFSは出力フィールドセパレーター、 ORSは出力レコードセパレーターという意味。) csv.awk BEGIN{ FS="\t"; OFS=","; ORS="\n"; } { printf $1 ","; } (終わり) ■3つのスクリプト言語の比較(python,perl,ruby) python,perl,rubyである。次のスクリプトは、いずれもコマンドラインから ファイルを読み込んで表示するものである。これはlinuxの端末でも、dosの 端末でもやることは同じである。読み込むファイルをsample.txtとすると コマンドラインでは一般に次のような命令になる python yomikomi.py samaple.txt perl yomikomi.pl tmp.txtと付け加えればいい。 python2で動くと思います 最初はpythonプログラムである。#の文はコメント行で、ファイルを 指定して読み込むとき使う。ここでは、インデントが重要。 yomikomi.py filename = sys.argv[1] # f = open("sample.txt","r") f = open(filename,"r") while True:      fileText = f.readline()      if not fileText:         break      print "<br>",fileText, f.close (終わり) perlはテキスト処理のためのスクリプト言語です perl、ここでも#文はコメント行、ファイルを指定して 読む込むとき使う、もちろんその時は#を取る。 yomikomi.pl # open IN, "sample.txt"; while(<>){      print "$_<br>"; } # colse ; (終わり) yomikomi.rb rubyのスクリプトで、pythonとよく似ている。 filename = ARGV[0] file = open(filename) while text = file.gets do   print text; print "<br>" end file.close (終わり) ■nikka.pl これは、webサーバーに載せて、perlで処理するための cgiである。 nikka.pl #!/usr/local/bin/perl require 'jcode.pl'; ( $sec,$min,$hour,$day,$mon,$year,$wday ) = localtime(time); $mon++; @week = ('日曜日 ','月曜日 ','火曜日 ','水曜日 ','木曜日 ','金曜日 ','土曜日 '); $wwday = $week[$wday]; $yeara = $year +1900; print "Content-type: text/html¥n¥n"; print "¥n"; print "日課を表示するテスト¥n"; print "¥n"; print "¥n"; print "¥n"; print "

$yeara年$mon月$day日$wwdayです

¥n"; if(($wday ==0){ print "日曜日課です
¥n"; open IN, "nitiyou.txt"; while(){ print "$_
"; } close IN; } elsif ($wday =6) { print "土曜日課です
¥n"; open IN, "doyou.txt"; while(){ print "$_
"; } close IN; } else { print "平日日課です
¥n"; open IN, "heijitu.txt"; while(){ print "$_
"; } close IN; } open IN, "owarini.txt"; while(){ print "$_
"; } close IN; print "作成者 ◯◯◯
¥n"; print "¥n"; exit; ■hindo3.pl レコード単位で頻度を取るには、 hind3.pl # csv用に出力をします。A>jperl hindo3.pl outfile.csv $/ = ""; $* = 1; while (<>){ @words = split(/\n/,$_); foreach $word (@words) { $wordcount{$word}++; } } foreach $word (sort keys(%wordcount)) { # print $word, ",", $wordcount{$word},"\n"; print $word, "\t", $wordcount{$word},"\n"; } 上の例はレコード単位に対して、頻度を取っています。 ここでslpit文の\nが改行を区切りにしてカウントします。 という意味です。これを半角スペースにすれば英語の文章に 対して出現する単語ごとに頻度を取ることができます。 索引などを作るときに便利でしょう。 jperlでもperlでも処理できます。 ■form.pl 住所、名前などデータテキストからタックシールなどに打ち出すのにperlを使っていたことがあった。perlを使うとこんな風になる。 form.pl #宛名書き # データの構造 namae,yuubin,jyusyo #perl>jperl form.pl ad.txt で実行する。<<<<は左詰半角4文字分 # フォーマットの構造は format =     . とする。 format = 〒@<<<<< $zipcorde ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< $address ~^<<<<<<<<<<<<<<<<<<<<<<<<<<< $address @>>>>>>>>>>>>>>>>> 様 $name . while (<>) { ($name,$zipcorde,$address) = split(/\,/); write; } (終わり) データの住所録(ad.txtの中身、仮名、仮想) 町谷 植男,238,布置市緑ケ丘 2ー6ー3  私の町アパート2345 隣野 真知子,267-11,才知市暮町 2ー451ー3 梅田 さくら,012-21,岡野市田舎 2ー354ー6 由葉 樹里,963-01,横町市布町神山 2ー51ー2 出力結果の一部(テキストファイル出力するには、>tmp.txt) 〒238 布置市緑ケ丘 2ー6ー3   私の町アパート2345 町谷 植男 様 〒267-11 才知市暮町 2ー451ー3 隣野 真知子 様 となります。上の例では、ブログ内では名前が左空白が無視されて左端に来ますが、実際の処理は右詰で右側に配置されます。 shift-jisの処理なのでjperlを使ってます。perlでは動きますが一部文字がおかしくなったりします。