X



awkについて語るスレ $2

■ このスレッドは過去ログ倉庫に格納されています
2007/02/23(金) 23:55:42
腐っても鯛? 騏も老いては駑馬に劣る?
三人の碩学が生み出したスクリプト言語AWKについて語るスレ

◆ 前スレ
awkについて語るスレ
http://pc10.2ch.net/test/read.cgi/tech/1023556171/

◆ 関係スレ
シェルスクリプト相談室
http://pc10.2ch.net/test/read.cgi/tech/1112553783/
AWKでCGI
http://pc10.2ch.net/test/read.cgi/php/1171804314/
【sed】シェルスクリプト総合@LINUX Part2【awk】
http://pc10.2ch.net/test/read.cgi/linux/1154578200/

◆ 参考
The AWK Programming Language (Brian Kernighan):
ttp://cm.bell-labs.com/cm/cs/awkbook/index.html

GAWK (GNU Projedt):
ttp://www.gnu.org/software/gawk/
337331
垢版 |
2010/02/28(日) 20:03:12
>>336
出来ました。まさか本日中に解決できるとは思いませんでした。
ありがとうございます。大変勉強になりました。
2010/02/28(日) 22:25:50
ボソ 本当に勉強になったかどうかは疑問だ・・・
 おっと一言オウかったか。
2010/03/04(木) 15:04:38
gsub()とかで引数に変数を利用したいのですがどうすればいいのでしょうか?
gsub(str1,str2)みたいに。
2010/03/04(木) 21:44:52
>>339
man gawkより
gsub(r, s [, t])
For each substring matching the regular expression r in the string t,
substitute the string s, and return the number of substitutions.
If t is not supplied, use $0. An & in the replacement text is
replaced with the text that was actually matched. Use \& to get a
literal &. (This must be typed as "\\&"; see GAWK: Effective AWK
Programming for a fuller discussion of the rules for &'s and
backslashes in the replacement text of sub(), gsub(), and gen sub().)
2010/03/08(月) 21:36:03
awk 'BEGIN{x="ABCDE";y="BCD";z="XXX";gsub(y,z,x);print x}'

何が難しいのかよくわからん。
342デフォルトの名無しさん
垢版 |
2010/03/17(水) 22:07:37
時々awkだと遅いのでperlに書き換えるという人がいますが、
実際のところ速くなるんでしょうか?
私の環境ではforループや加算などはawkのほうが速そうですが、
どのような処理の場合にperlのほうが速くなりますか?

$ time mawk 'BEGIN{x=0;for(i=1;i<=1000000;i++){x=x+i};printf("%f\n" ,x)}'
500000500000.000000

real 0m0.131s
user 0m0.120s
sys 0m0.000s
$ time gawk 'BEGIN{x=0;for(i=1;i<=1000000;i++){x=x+i};print x}'
500000500000

real 0m0.289s
user 0m0.284s
sys 0m0.000s
$ time perl -e '$x=0;for($i=1;$i<=1000000;$i++){$x=$x+$i};print $x'
500000500000
real 0m0.379s
user 0m0.376s
sys 0m0.004s
2010/03/17(水) 22:26:14
>>342
「awkだと遅いのでperlに書き換えるという人」 に聞けば分かる
2010/03/19(金) 09:08:06
>>342
遅いというawkはgawkなの?
素のawkよりgawkの方が早くなかったっけ?
2010/03/20(土) 01:03:01
カーニハンとパイクの『プログラミング作法』にawkとperl
(とCとC++とJAVA)の比較があるな

今のマシン使って書き換えなきゃならないほど遅いって
どんな処理なんだろう?
2010/03/21(日) 13:44:10
>342
awk 等を組み合わせて実行するとプロセス起動のコストがかかるので perl で一つに纏める、という話じゃないの?
347デフォルトの名無しさん
垢版 |
2010/03/22(月) 17:35:11
文字コードのコードを変数にして文字列を操作することってできますか?
文字列中の全角文字を半角文字に変える華麗な方法を模索しています。
2010/03/22(月) 18:01:58
Use iconv.
2010/03/22(月) 18:25:10
> 文字コードのコードを変数にして文字列を操作することってできますか?

なにをしたいのかよくわかんないんだけど。

> 文字列中の全角文字を半角文字に変える華麗な方法を模索しています。

華麗なのはtrコマンドを使う方法。ただtrがマルチバイトをうまく扱ってくれるか
どうかはこころもとない。
Perlならtrを、Rubyなら文字列クラスのtrメソッドを、
Pythonならstringモジュールのmaketrans関数と文字列のメソッドtransleteを使う、
という手がある。
awkないし(tr以外の)古典的なツールで華麗にやる方法はないと思う。
350デフォルトの名無しさん
垢版 |
2010/03/24(水) 17:11:16
Excelで
全角半角変換は ASC()
半角全角変換は JIS()
2010/03/25(木) 08:34:11
>>347
1. EUC-JPにして(nkfとか)kakasi で、戻す
2. それだったら最初から、nkf -Z
3. gawk前提で、文字毎に処理(LANGを指定して子プロセス起動)

awkの中で閉じてやるのはめんどくさそう
2010/03/29(月) 23:34:27
gawk 3.1.6
system(cmd) を使うと、アンチウィルスソフト(kaspersky)の
アプリケーション履歴にバッチファイルが登録されるのを発見。
close(cmd) しても同じ。

while(cmd|getline>0){}
で代用すると残らなくなった。??
2010/05/13(木) 00:22:57
仏でブルカ否定の決議採択 「国の価値観と相容れない」
http://www.cnn.co.jp/world/AIC201005120004.html

テヘランで、ブルカを着て入出国する時って、顔のチェックどうするんだろう。
他人や男でもばれないの?
2010/05/13(木) 00:23:49
>>353
誤爆スマン
355デフォルトの名無しさん
垢版 |
2010/05/14(金) 13:38:24
http://pc11.2ch.net/test/read.cgi/linux/1215431118/65
2010/05/18(火) 10:51:40
awkのprintについてご教示下さい。

下のような出力が有った場合、例えば
lrwxrwxrwx 1 root root 70 May 18 10:37 hoge

ls -al | awk '{print$1$2$2$4$6$7$8$9}' とすれば「$5」の
「70」を抜くことが出来ますが、これが$100とかまで続く場合、
「$5」だけを抜きたい場合記述が大変になります。

何か良い方法は無いものでしょうか?
2010/05/18(火) 11:01:32
$nに代入があると、その時点で$0が再構成される。

区切りの空白が$5のあったところだけ2個になるのが気にならなければ、
ls -al | awk '{$5 = ""; print}'
とすればよい。

空白2個を修正するならこうする。
ls -al | awk '{$5 = ""; print $0}' | awk '{$1 = $1; print}'
2010/05/18(火) 11:03:15
$0 は余計だった。
ls -al | awk '{$5 = ""; print}' | awk '{$1 = $1; print}'
2010/05/18(火) 11:07:03
2つめのawkの$1 = $1は何のため?
2010/05/18(火) 11:34:06
なにもしないと、$0は読み込んだそのままなので空白2個は空白2個のまま。
$1=$1で代入してやると、$1, $2, ...を空白1個でつないだものが$0に代入されるので、
空白2個だったところが空白1個になる。
2010/05/18(火) 11:35:04
2つめのawkに食わせた時点で$n (n>0)は詰まるけど$0は入力行そのまま
空白2個なので$0を再構成すると空白1個区切りになる
2010/05/18(火) 12:21:12
>>357-358
非常に解りやすいご説明、ありがとうございます。
なるほど代入することで解決するんですね。
勉強になりました。
2010/05/18(火) 15:08:38
$1 = $1 ってイマイチよく解らん

$1ってFSで区切られた一つ目だよね?
なんでそれ自身を自分に代入したらスペースが消えるん?
2010/05/18(火) 15:27:35
$0の再構成が行われるからって説明されてるだろ。

$0の再構成とはいったんばらした$1,$2,...をOFSを挟んで
つなげ直すってことなので、何で区切られていたかは
保存されない。
2010/05/18(火) 15:41:56
>>364
>$1=$1で代入してやると、$1, $2, ...を空白1個でつないだものが$0に代入される

って約束事を覚えておけってことかい?
2010/05/18(火) 15:42:39
ちょっと気になって試してみた。

% echo a b | gawk '{OFS="-";$1=$1;OFS="=";print}'
a=b

再構成は$1=$1をやってすぐじゃなくて、次に$0が使われるとき、ってこと
なのかな?
367365
垢版 |
2010/05/18(火) 16:27:59
解った

http://www.kt.rim.or.jp/~kbk/gawk-3.1/gawk.html

警告: 一部のバージョンのawkは NFを減じたときに$0の再構築を行わない。
結局のところ、awkにレコード全体の再構築を強制したときにはその時点で
フィールドの値とOFSが使われる。再構築を行うためには、何らかの無害な
代入を行う:

$1 = $1 # force record to be reconstituted


賢くなった。あんがと。
2010/05/18(火) 16:46:58
awkは奧が深いのぉ
2010/05/19(水) 22:24:52
久しぶりにいいもんを見させてもらいますた><
2010/05/24(月) 09:55:14
知らなかった。
勉強になった。
2010/05/24(月) 15:25:46
みんな>357のお蔭で多くを学んだな。
372デフォルトの名無しさん
垢版 |
2010/05/29(土) 04:53:07
名前:
E-mail:
内容:
cygwinだと
% cut -f1 -d, hoge.csv
より
% awk -F, '{print $1}' hoge.csv
の方が速かった。
#実行時間ね
#Perl?シラネ
2010/06/07(月) 11:45:38
>>372
sed -e 's/,.*//'でもawkと同じくらいだから、cutの実装が遅いんだね。
cutが無駄にオプション多い所為じゃない?
2010/06/07(月) 12:04:05
手元のlinux環境だとcutの方が速いという普通の結果でしたが。
hoge.csvは6桁の乱数3つを「,]で区切って並べた100万行の
ファイルです。

% time cut -f1 -d, hoge.csv >/dev/null
cut -f1 -d, hoge.csv > /dev/null 0.21s user 0.01s system 99% cpu 0.222 total
% time awk -F, '{print $1}' hoge.csv >/dev/nulll
awk -F, '{print $1}' hoge.csv > /dev/nulll 1.52s user 0.03s system 99% cpu 1.558 total

ちなみにバージョンは

cut (GNU coreutils) 8.5
GNU Awk 3.1.7
2010/06/07(月) 12:22:48
あーなるほど、なんか判った。cygwinのfgetc()が遅いからじゃないかな。
fgetc()とfgets()で時間を較べたときにfgetc()の方がずっと遅かった記憶がある。
2010/09/13(月) 14:14:54
xgawk (gawkでなく)にとあるwebページを食べさせると、XMLERRR (not well-formed)で中断します。
そのページがwell-formedか極悪かは私にとってどうでもよく、単に内容を得たいだけなので、文末まで処理し終えて欲しいのです。
どうにかならないでしょうか。
2010/09/25(土) 14:55:22
シェルスクリプト内でパイプ入力されたものを処理する
アクションをヒアドキュメントで書く事は出来るでしょうか。
2010/09/27(月) 14:57:18
質問です。
データが
|1|aaa|
|2|bbb|
|3|ccc|
などとなっているとき
aaa
bbb
ccc
を取り出そうとして
awk 'FS="|"{print $3}' ファイル名
としたんですが、1行目だけがうまくとれません。
データファイルの1行目を空行にすれば解決できないことはないんですが、
空行を入れ忘れてしまう懸念があります。
どうすればいいんでしょうか?
2010/09/27(月) 15:01:46
やりたいことは awk 'BEGIN {FS="|"} {print $3}' じゃないかと思うんだけど
2010/09/27(月) 15:08:38
378です。
>>379
どうもありがとうございました。
2010/09/27(月) 18:42:12
gensub()にて、マッチした10番目以降のグループの指定の仕方を教えてください。
下記サイトでは、17番目まで普通に指定できるような事が書いてあるけど、
http://tounderlinedk.blogspot.com/2010/08/gensub-n-awk.html

gensub(pattern,"\\10","g",$2) とかくと
\\1(マッチ箇所)と0(文字)として解釈されちゃって上手くいなかい。

シェルスクリプト風かと思って、\\{10} も試したけどダメダッター。

GNU Awk 3.1.5です。
382381
垢版 |
2010/09/27(月) 19:00:47
BSDのjmanには、1から9までの数字って明記されてるなあ。
実装によって違うのかなあ
パターンを動的に生成してマッチさせようとしてるから結構困る(´・ω・`)
http://www.linux.or.jp/JM/html/GNU_gawk/man1/gawk.1.html
2010/09/27(月) 19:04:47
>>381
マニュアルには1から9までって書いてあるし

Within the replacement text s, the sequence \n, where n is a digit from 1 to 9, may be
used to indicate just the text that matched the n'th parenthesized subexpression.

ソースの該当箇所(builtin.cの2542行目あたりから)みても1桁限定のロジックだよ。(3.1.7調べ)

int dig = scan[1] - '0';

なんてやってる。
2010/09/27(月) 19:08:03
一旦ぶった切るしかないんじゃね
385381
垢版 |
2010/09/27(月) 19:12:31
>>383
どうもありがとうございます。

>>384
ちょっと見栄え悪くなるけどそうする(´・ω・`)
2010/09/27(月) 21:27:29
>>381
なんでそこのひとは16までできたんだ?
2010/09/28(火) 00:32:52
10の代わりに:を使っていたりして。
2010/09/28(火) 03:15:24
このスレが盛況なのが珍しいから
記念パピコ。
2010/09/28(火) 03:41:50
15年以上前だけどawkの勉強始めて同時にperlの勉強もしてたら
気付いたらperlばっかりやっててawkすっかり忘れてしまったなぁ
今はperl捨てて専らpythonやってるけどawkもいいよね
2010/09/28(火) 09:40:13
Busyboxに組み込めば、それこそ炊飯器や冷蔵庫でも動くからなあ。
手軽であるにも関わらず、結構高度な処理もガリガリ書けるから好き。

Cとシェルスクリプトが好きだから、文法的にもしっくり来る。
上位互換のPerlも大好き。
2010/09/28(火) 14:37:59
>>376ですが、誰もかまってくれないので寂しさで死にそうです。
2010/09/28(火) 14:52:08
>>391
どれでも好きなのを選べ

1. xgawkを改造
2. エラーになるXMLを事前に修正してwell-formedにしてから食わせる
3. xgawkは捨てて別の言語、ライブラリを試す
2010/09/28(火) 17:23:08
jawkがjwalkに見えてしまう
2010/10/01(金) 11:21:26
動く環境の多さ順にインタプリタを選ぶんなら、

シェルスクリプト > awk >>> perl >>>>> python >>>>> ruby >>> haskel etc.

となるだろうな。

シェルスクリプトはシェル依存な部分が多く、perl ほど高機能なものも要らない。
そんな時、小さな端末でもスマートに動いてくれる awk にちんこ勃つ。

>>389
言語に捨てるも拾うもないよ。その時々に都合の良いものを組み合わせて使うのがUNIX的な発想。
2010/10/01(金) 15:33:40
>>394
「一発やろう」ですね!
2010/10/09(土) 04:40:48
awk最近勉強してる。perlより全然簡単。
これなら俺でも挫折しなくてすみそう
2010/10/09(土) 04:57:14
>>396 がんば!
2010/10/21(木) 20:16:46
sjisで書いた
/ー/{print}
を実行すると

awk:
awk: ^ 正規表現が終端されていません。
awk: 致命的: [ または [^ が対応しません。: /[/{print}/

のエラーになってしまいます。
ーの2バイト目が[なせいだと思いますが、どう対応したらいいでしょうか?
入力ファイルはsjisで書かれていて、文字コード変換はできません。
2010/10/21(木) 20:55:41
>>398
環境の問題なんだから、実行環境くらいまともに書けよ。
2010/10/21(木) 21:38:24
>>398
gawk を使う
2010/10/21(木) 22:52:57
環境はCentOS-5.5-x86_64でGNU Awk 3.1.5です。
/bin/awkはシンボリックリンクで、実体はgawkでした。
2010/10/21(木) 23:49:35
>>401
--help 嫁
2010/10/22(金) 01:41:07
Windows7(64bit)で使えるawkありますか?
2010/10/22(金) 02:19:30
32bit版のawkをを使うんじゃダメ?
405398
垢版 |
2010/10/22(金) 07:32:34
こうすることで対応できました。
/\x81\[/{print}
2010/10/22(金) 09:41:36
それでいいなら、/ー[]/でもいい希ガス。
根本的な解決になってないけどねぇ。
2010/10/22(金) 13:52:10
シングルクオーテーションやダブルクオーテーションの使い分けじゃね〜
408398
垢版 |
2010/10/22(金) 19:55:53
根本的な解決するとしたら文字コードを変えることでしょうか?
2010/10/22(金) 20:03:18
日本語の文字コードに対応してるawkを使う、という方法もある。
今あるのかどうか知らないけど。
2010/10/22(金) 20:28:38
今のgawkは普通にUnicode対応してるみたい

$ echo 'てすと' | gawk '/[ぁ-ん]/ { print length($0) }'
3

UTF-8ロケールでしか試してないけど
cygwinでも大丈夫
2010/10/23(土) 01:29:00
>>404
gawkでいいかな
412399
垢版 |
2010/10/23(土) 06:55:10
>>405

問題は解決したのかもしらんが、一応。
以下2つのWin用バイナリは問題ないので、ソースもらってLinux上でコンパイルしてみたら?

ttp://gnuwin32.sourceforge.net/packages/gawk.htm
ttp://www.kt.rim.or.jp/~kbk/gawk-3.1/
413398
垢版 |
2010/10/23(土) 10:53:14
サーバ管理者じゃないのでサーバをいじることはできないです。
これにしたらsjisでも動くようになるのでしょうか?
2010/10/23(土) 12:27:19
>>413
少なくとも自分が試したWindows2003上ではな。

▽tes.awk ※sjis
/ー/{print}


CentOS5.5上
$ gawk -f tes.awk readme.ja
awk: tes.awk:1:
awk: tes.awk:1: ^ 正規表現が終端されていません。
awk: tes.awk:1: 致命的: [ または [^ が対応しません。: /[/{print}/

Windows2003上
> gawk -f tes.awk readme.ja
⇒マッチした物が表示される

Linux上でロケールをsjis.japaneseとかにすればいいのかと思ったが、ロケール変更自体がうまくいかなかったわ。
困ってる事があるなら、最終的に何がしたいか言ったほうがいいよ。
415398
垢版 |
2010/10/23(土) 12:40:31
Windows2003だとちゃんと動くんですね。
困っていたことは405で解決したので大丈夫です。
今は「根本的な解決」に興味があったのでお聞きした次第です。
416初心者
垢版 |
2010/11/04(木) 22:14:10
awkでシェルのPATH変数をマッチさせるときにスラッシュ//を使わない方法を教えていただけませんか?
2010/11/04(木) 23:14:10
>>416
初心者だからマルチが許されるとでも思ったか?
418初心者
垢版 |
2010/11/05(金) 06:32:09
ごめんなさい!
知りませんでした。
2010/12/15(水) 01:54:35
配列の要素数を調べるなら、ループ処理しないと分からない?
length みたいなのは無い?
2010/12/15(水) 02:27:50
あるよ。まさしく、length(array)。
2010/12/15(水) 02:42:46
そんなもんねぇよw
と思ったらgawkにはあるのか

length([s]) Returns the length of the string s, or the
length of $0 if s is not supplied. Starting
with version 3.1.5, as a non-standard exten-
sion, with an array argument, length() returns
the number of elements in the array.
2010/12/15(水) 04:20:37
むしろ配列が存在するってことはその配列を作成する過程があるだろ?
作成するときに数えればいいんじゃね?
2010/12/15(水) 08:40:15
連想配列だったら数えないのが普通だがな
424419
垢版 |
2010/12/25(土) 03:12:23
function で処理する時、配列だけではダメで要素数まで必要なんだかなぁ、
って事が分かりますた
425デフォルトの名無しさん
垢版 |
2010/12/28(火) 11:29:35
function に渡すだけなら要素数なんていらないんじゃない?
426デフォルトの名無しさん
垢版 |
2010/12/28(火) 13:55:13
$1 = $1みたいなトリックを見る度に奥が深いと言うよりは糞に見えてきます
翻すとUNIX文化そのものが
まあ、あくまでおれの主観ですがね
2010/12/28(火) 15:24:21
>>426
awk大好きなオイラに喧嘩売るのかw
ウニックス文化最高!(NT系はUNIXのパクリ)
2010/12/28(火) 15:28:13
>>427
全角英字使う奴が awk 大好きだとは到底思えん
2011/01/05(水) 23:22:55
まあ冬休み期間だものね。
2011/01/06(木) 00:22:04
▼tes09.awk
BEGIN{
  if (ARGV[1]=="")
    ARGV[1]="hoge.txt"
  while (getline < ARGV[1] > 0) print "BEGIN\t"$0
}
ARGV[1]=="hoge.txt"{
  print "BODY\t"$0
}

★質問
上記スクリプトを引数を付けた場合と付けない場合をそれぞれ実行しました。

▼gawk -f tes09.awk hoge.txt
BEGIN  arima_yuuichi@example.com
BEGIN  ooizumi_sadawo@example.com
BEGIN  taguchi_kenji@example.com
BODY  arima_yuuichi@example.com
BODY  ooizumi_sadawo@example.com
BODY  taguchi_kenji@example.com

▼gawk -f tes09.awk
BEGIN  arima_yuuichi@example.com
BEGIN  ooizumi_sadawo@example.com
BEGIN  taguchi_kenji@example.com

ここで、BEGIN句での ARGV[1]="hoge.txt" という代入を本編(?)でも有効にする為
にはどうすればいいでしょうか?
2011/01/06(木) 00:31:45
なにもしなくても有効だと思うんだけど
質問の趣旨がわからん
432430
垢版 |
2011/01/06(木) 06:20:53
分かり辛くてすみません。
hoge.txtの中身は下記です。

arima_yuuichi@example.com
ooizumi_sadawo@example.com
taguchi_kenji@example.com

>>430はWin32のバイナリ「GNU Awk 3.1.7(windows special Nov 24 2009)」を使用した結果です。
下のほうの実行結果では、BEGIN句でのARGV[1]への代入はBEGIN句では有効ですが、
本編では有効になっていないので出力されていないように見えます。

ちなみに、CentOS5.5上の GNU Awk 3.1.5 では下記エラーになりました。


gawk: tes09.awk:2:   if (ARGV[1]=="")
gawk: tes09.awk:2: ^ 表現の char '・' は不正です。
2011/01/06(木) 08:57:49
入力レコードが1件も無いからでしょ

>gawk: tes09.awk:2: ^ 表現の char '・' は不正です。
これは全角スペース
2011/01/06(木) 09:12:00
>BEGIN  arima_yuuichi@example.com
>BEGIN  ooizumi_sadawo@example.com
>BEGIN  taguchi_kenji@example.com
コレはgetlineで読んで出力したもの

>BODY  arima_yuuichi@example.com
>BODY  ooizumi_sadawo@example.com
>BODY  taguchi_kenji@example.com
コレはコマンドで指定したファイルから出力したもの

たとえば
{
  print "BODY\t"$0
}
としてやれば明らか
435デフォルトの名無しさん
垢版 |
2011/01/06(木) 13:46:53
質問の趣旨は、プログラム(スクリプト)の中で入力ファイル等の
コマンドライン引数を追加したいという事ですか。

コマンドライン引数の配列は ARGV ですが、コマンドライン引数の
個数を格納する ARGC という組み込み変数があります。

ARGV配列を追加したら一緒に ARGC を修正してあげないと、awkは配列が
追加された事を認識しません。

BEGIN内でARGV配列を追加した分だけARGCをインクルメントしてあげれば
追加されたARGV配列で指定されたファイルも本文の処理に渡されます。

蛇足としては、
現在処理中のファイル名が格納されている配列 ARGV のインデックスを
示す組み込み変数は ARGIND です。

私のは Win版の gawkm115 です。スクリプト内でARGV/ARGCを操作しても
期待通り正常に動きますよ。

試してみてね。
436430
垢版 |
2011/01/06(木) 23:56:01
皆様レスありがとうございます。

>>433
>これは全角スペース

お恥ずかしい限りです(汗) 出勤前に思いつきで試したもので、スレ用に書いた
物をそのままコピってました・・・

>>434
BEGIN句のgetlineではARGV[1]への代入ができているのに、本文では有効に
ならないという事を伝えたかったのです。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況