awk ファンクラブ
ruby -ne 'puts split[2]'のほうが楽、と思ったけど 空行とかでの扱い考えると ruby -ne 'puts split[2] || ""' になるのか。やっぱawkが楽だな。 sedのスレとかあったので、思わず「なんでawkを使わない?」って突っ込んでしまったけど、 実はおれも長らくsedからawkへ行けなかった。田中さん(緑のSerrow)が月刊asciiに書いた 記事を読んで使えるようになったのだった。 いまではperlも使うが、やはりawkが楽だなぁ。16進→10進変換の関数作ったり、 バイナリデータ読むためのコードをCで作ったりして無理やり使ってたころが 懐かしい。 2年くらい前からLinuxを本格的に使い始めたけど awk(gawk)とsedには特に力を入れて勉強してる gawkは機能が洗練されて美しいし直感的で使いやすい リファレンスもとてもしっかりしてる おれが一番よく使うのは連想配列。 gawk '{w[$1]++;}END{for(i in w)print i,w[i];}' xxxx.txt | sort みたいなことを何百回やったことか。 わらうw ttp://awk.info/?doc/dsl/awkplusplus.html object_variable = class_name.new[(optional parameters)] object_variable.method_name(parameters) object_variable.delete みなさん教えて下さい。 一行毎に読み込み@<と@>で囲まれた部分を ランダムなアルファベット10文字に置換し、 元々@<@>に囲まれた部分の文字列と置換したランダムな文字列の対応を 別ファイルに書き出し っていうのをやりたいです。 awkとsedでできるの? pythonで書くべき? できるっちゃーできるが、おすすめはしない。 BEGIN { output = "hoge.txt" chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" len = length(chars) srand() } { if(match($0, /@<.*@>/)){ t = substr($0, RSTART+2, RLENGTH-4) if(!(t in m)) m[t] = rndstr(10) $0 = substr($0, 1, RSTART+1) m[t] substr($0, RSTART+RLENGTH-2) } print } END { for(i in m) print i, m[i] > output } function rndstr(n, s){ while(n--) s = s substr(chars, int(rand()*len)+1, 1) return s } printfと$ / $がうまく両立できない・・・ 文型向け授業でわざわざlinux使わせるなよ・・・ やっぱAWKいいよねー 「プログラミング言語AWK」は買い逃してたんで再販速攻で買ったよ。 Excelなんてやってられねーっつーの >>37 Excelのvlookupみたいなリレーショナルな事がやりたい場合ってどーしてる? いやさ、複数のシートから引っ張ってくるような感じで、複数のテキストファイルを対象にしたい時。 >>41 > そんなん普通に複数ファイル処理すればいいやん。 「普通に」の所kwsk awk初心者です。質問させてください。 awkでアクセスカウンタを作ろうと思い、 以下のようなスクリプトを書いたのですが、 最後のhtmlへの出力(表示)の方法がわかりません。 どうしたらいいのでしょうか? BEGIN{ #プロセスロック lock() #カウント数の読み込み while (getline < count.dat > 0){ before_count = $1; } close(count.dat); #カウントを1進める new_count = before_count + 1; #数字の置換を行う sub(before_count, new_count, $1); #プロセスロック解除 unlock() } print "Context-Type: text/text"; print "\r"; END{ #表示テンプレートの読み込み while (getline < count.txt > 0){ txt_file[++i] = $0; } close(count.txt); #あらかじめセットしてあるテンプレート上の文字列を置換 gsub("<!--#count.cgi--!>", new_count, $0); print $0; } >>43 getline知らなかったわ。 難しそうだな・・・ >>44 SSIの仕組みは理解できていますか。 ttp://httpd.apache.org/docs/2.0/ja/howto/ssi.html getline は毎回リファレンス見に行ってるなぁ 頭が劣化しとるわー こんなものが落ちてたw ttp://mitya.pp.ru/chamberlen/assorted/OReilly%20-%20Sed%20&%20Awk%202nd%20Edition.pdf Mac OS X Leopard 10.5.8でjgawkを使いたいのです。 ターミナルでawk '{print $0}' filenameですと日本語が悲しいです。 お使いのみなさん、使用法等教えて下さい。 awk初心者です。 awkにはperlのjoinみたいの関数ありますか? perl: print join(":",$_); >>54 BEGIN {OFS=":"}{$1=$1;print} 重複を削除するBASHスクリプトに、perlの部分はawkの連想配列で書き換えたいんですが、splitした後の処理方法が分かりません 教えて頂ければ幸いです。 ----------------------------- hoge='a:b:c:d:a:b:c:d:a' echo -n $hoge | perl -F: -ane 'chop;foreach(@F){$s{$_}++ or push(@b,$_)}print join(":",@b)' ----------------------------- 素人なりですけど echo -n $hoge | awk 'BEGIN{OFS=":"}{n=split($0,a,":");m=1;for(i=1;i<=n;i++){if(!(a[i]in b)){$m=a[i];b[$m]++;m++}}print}' echo -n $hoge | awk 'a[$0]++<1{printf(NR>1?RS:_)$0}' RS=: a[$0]++<1 じゃなくて !a[$0]++ とした方が1バイト短くなるな って、そういう趣旨じゃないか >>58 ,59,60 ご回答、誠に有難うございました! まだawkの部分理解してないけど、期待通りの動作が確認できました! Linuxじゃないんですが、Gawk on Windowsだと、 gawk '{print $1;}' data.txt ていうのは、クォーテーションはダブルにしないといけないんですね。。。 うん、引数文字列をどう解釈するかは awk じゃなくてシェルだから。 cmd.exe の仕様の問題であって、awk の側では対応しようにもできない。 BEGIN { printf "256倍のコードが提供されてる\n" printf "ttp://books.ascii.jp にアクセス\n" printf "本には4756101623なんてのがついてるけど、本の通りに入れるとnot found\n" } END { print "昔と本の内容が変わってるみたいだな" } END { print "まだ始まってもねーよっ!" } BEGIN { printf "・・・ごめ・・・\n" } { if ($0 == "aka") print "red" else print "blue" } の最も変態的な記法を教えて下さい。 END { system("echo " + $0 + " | perl -ne 'if(/"aka"/){print \"red\";}else{print \"blue\";}'") } awkでシェルのPATH変数をマッチさせるときにスラッシュ//を使わない方法を教えていただけませんか? perlだと##で行けますが ごめんなさい! マルチがだめとは知りませんでした。 awkって今時オブジェクト指向もサポートしてねぇのか。 だせぇ・・・ とか思ってたらこんなのもあるんだな。 http://awk.info/?doc/dsl/awkplusplus.html awkの処理についてアドバイスを下さい。 スペースで区切られたテキストファイルがあります。 例(フィールド数も文字数も全部異なります) abc efg hij http://www.example.com/index.html xyz 123 http://www.example.org/ she good love look good 4edi http://www.example.net/test/test.html こんな感じのテキストファイルからURLだけを抽出したい 場合、どう言った処理を行うと良いでしょうか? printなどは使えそうにないし頭を抱えています。 是非お助け下さい。 >>76 {for(i=0;i<=NF;i++)if($i ~ /^http:\/\/.+$/)print $i} 自分は match($0, /http:\/\/[^ ]+/, f) を使う気がする。 #!/bin/sh cat 入力ファイル | tr ' \t' '\n' | awk '/^http:/' …まで書きかけて、あれ、これawkじゃなくてgrepで良くね、と思ってしまった俺 /bin/shでもやはり自分は expr 文字列 : '.*\(http:\/\/[^ ]*\).*' を使う気がする。 うちは>>77 の条件を index($i, "http:") == 1 で書くだろうなぁ でも、処理内容がそれだけなら sed -n 's/^.*\(http:[^ ]*\).*$/\1/p' だなぁ 避けられるなら正規表現は避けたほうが速いんじゃないかと思ってる まだどうしてそういう結果になるのか…が全然解らないのですが 一つ一つひもといて自分のものにしていきたいです。 みなさん本当に色々ありがとうございます。 こういうのもpythonで書くようになってしまった俺は駄目なやつですか 流石にPythonはこういうサクッとしたテキスト処理には冗長すぎないか? awk以外でならperl、さもなくばrubyあたりまでが俺は限度だなあ BEGIN{ FS="http:// "; }{ split($2, item, / /); print FS item[1]; } とか 入力からランダムで1行表示する awk '{ l[i++]=$0 }; END{ srand(); print l[int(i*rand())] }' シェルスクリプトの方が短いか? こう書くと1行しかメモリに保存しないので入力行が多くとも平気です BEGIN { srand() } rand() * NR < 1 { x = $0 } END { print x } >>87 それだと行数が多いと後半の表示が少なくなっちゃう >>88 2行のときは 1/1の確率で1行目が選ばれる →1/2%の確率で2行目が選ばれる 3行のときは 1/1の確率で1行目が選ばれる →1/2の確率で2行目が選ばれる(この時点で1行目、2行目の確率はともに1/2) →1/3の確率で3行目が選ばれる(2/3の確率で1or2行目が残り両者1/2なので全て1/3) のように、基本的に確率は等しいはずですが…… 浮動小数点演算の精度が問題になるような行数の話でしょうか? >>87 お、これはすごい!考えたなー。ぱっと思いついた奴は、天才だ。こんな風になりたいわ。 > 浮動小数点演算の精度が問題になるような行数の話でしょうか? これは初め見たとき思ったけど、それが問題になるなら、 私の書いた方法でもメモリが逼迫してまずい気がします。 ただ、精度やrand()の性能で、実際に統計取ったら88の言うようになるのかもしれません。 あとは、rand()が1を返す実装はないよね?gawkのマニュアル読んで書くのだけど、 関数の説明が簡単に書き過ぎていて、ちょっと不安。 不要な部分を全部削って87の方が2バイト短いか。 mawkだとsrand()を省けるから、もっと短い。エレガント! それにしても、4ヶ月ぶりに上がったんだ。ほんと人居ない。 空行を削除する awk 1 RS= sedだと、 sed /^$/d かな?同じ9文字か。 >>89 rand()を全行で実行しているから、 1行目には2行目以降が x を上書きする確率が加わり、 2行目には3行目以降が x を上書きする確率が加わり、 ってことになるんじゃないのかな。 全4行の場合 1行目が表示される確率 1/1*1/2*1/3*1/4 2行目が表示される確率 1/2*1/3*1/4 3行目が表示される確率 1/3*1/4 4行目が表示される確率 1/4 って感じで、最終行が表示される確率が一番大きい気かします。 rand()をBEGINの中に入れてしまえば全部同じだけど。 >>96 1/1*1/2*1/3*1/4 + 1/2*1/3*1/4 + 1/3*1/4 + 1/4 = 5/12 (≠ 1) なので、それが誤りなのは、すぐに分かるはずですが…… それらの確率を足したら1になっていないといけません ここは高校数学の確率統計のお話をするスレではありませんが、 以下のように考えたらお分かりでしょうか? 1行目が表示される確率は 1/1*1/2*2/3*3/4 = 1/4 (1行目が選ばれる確率 * 2行目が選ばれない確率 * 3行目が選ばれない確率 * 4行目が選ばれない確率) 2行目が表示される確率は 1/2*2/3*3/4 = 1/4 (2行目が選ばれる確率 * 3行目が選ばれない確率 * 4行目が選ばれない確率) 3行目が表示される確率は 1/3*3/4 = 1/4 (3行目が選ばれる確率 * 4行目が選ばれない確率) 4行目が表示される確率は 1/4 (4行目が選ばれる確率) >>97 そうでした。電車の中で気が付きました。 x が上書きされる確率じゃなくて、上書きされない確率を掛けないといけませんでした。 納得。 なんか利点が無いように見えるので、sedじゃなくawkを使う理由を探してみた。 tar xf linux-2.6.39.1.tar.bz2 --wildcards '*.c' -O >src.txt time cat src.txt |awk 1 RS= >/dev/null real 0m3.172s user 0m2.786s sys 0m0.757s time cat src.txt |sed /^$/d >/dev/null real 0m32.503s user 0m31.465s sys 0m0.882s ※参考 time cat src.txt |cat >/dev/null real 0m0.606s user 0m0.036s sys 0m0.586s おー。sedより、ずっとはやーい やったね、awk! うむ。grep よりも awk の方が速かった記憶がある。 複数のtimeコマンドの出力から平均を求める awk -Fm '{ a[$1]+=$2; a[0,$1]++ }; END{ for(i in a) if(i~/^[rus]/) printf "%sm%.3fs\n",i,a[i]/a[0,i] }' 昨日の時間計測のために書いた。 いろいろ問題あり。これ以上短くかけなかった、残念だわ。 sedがすっごい遅いので全部メモリに読み込んで処理させてみた。 time cat src.txt |sed -n '1x;1!H;${x;s/\n\n\+/\n/gp}' >/dev/null real 0m24.515s user 0m18.584s sys 0m2.005s # ちなみに、昨日のも含めて3回試した結果を平均した …やっぱ遅い。GNU sedが悪いの?スレ的に満足な結果だけど。 便利で速くてシンプルなのに、あまり使われない紹介されない、消え行くawk、カワイソス フィールドを抜き出すワンライナーはやっぱawkでしょ perl -pae'$_=$F[8].$/' ruby -nae'puts$F[8]' awk 'print$9' >>95 の表記初めて見た このスレの住民にはこれくらい当たり前なのか… それってどういう構造なんだ? 1番目の引数である「1」は「パターンは常に成り立つ、アクションは指定しない(=レコードを加工せずに出力)」というawkコードだろうけど その次の引数って入力ファイルになるはずじゃ? わかんねー。なんでこれをコマンドプロンプトに打ち込んで、うまくいくのか。 gawk 1 RS= testfile.txt RSが空だとRS=\n+として解釈されるんじゃまいか だとしても、何故にRS=\n+がコードとして実行されるの? コードは1で終わってね? 自己解決、assignment optionsなんて仕様があったのか おー、いっぱい居るね!まだまだやれるぞ、awk! 一応説明すると、プログラム自体は>>104 の解釈の通りです。 また、RS=""なら、RS="\n\n+"とほぼ同じです。 違いは、RS=""はファイルの先頭に改行が続くとき、それを無視します。 ついでに、POSIXではRSに2文字以上設定すると、結果は不定とされています。 gawkでは、正規表現を使える拡張がされていますけど。 引数ですが、ここに代入文を書くとBEGINの後に処理されます。 まあ、ああ書いたのは-vオプションを使うと3文字コマンドが増えるからなんですが、 こういう変数の設定方法もあるということで。 awk /./ の7文字だけでOK RSは初期値が入ってるんだから そうか、sed /^$/d って grep . で良かったんだな >>109 書き忘れ。 RS=""のとき、ファイルの末尾の改行も無視する。 あと、FSが"\n"に設定されているように振舞う。 元々複数行を一気に処理したい場合に使うことを想定してたのだろう。 >>110 ああ、すごい、これは短い!頭柔らかいねえ、スマートだわ。 夢の中でも考えたのに…無能過ぎワラタ >>111 grep最強伝説はっじまっ…らないぞ。同じ方法で時間計測したら2時間半たっても終わらない。 grep捨ててawkを使おう! 改行をWindows向けに置き換える awk '{ print $0 "\r" }' こっちの方が速くて短いか。 awk 1 ORS='\r\n' 速くて短いし、そっちのがコードと意味が一致するかと そっかー、分かり易さは、上の方だと思ったのですよ。 下のは、awkがどう動くかを知ってないと気持ち悪い感じ。 101みたいなsedスクリプトを、初めて見たときのような。 上だと\n\rになっちゃうけど CRLFの\r\nとは違うから Windowsでは認識しないのでは? >>117 いや、上のコードは\rが先に出力されるからあってるよ、改行じゃなくて普通の可読文字でためしてみ Windows向けの改行をUnix向けに置き換える awk 1 RS=\\r ORS= 改行弄ったら戻したいよね。一文字多い別解。 awk 'sub(/\r/,"")' >>117 $0にRSは含まれない。print文での出力のときにORSが付けられる。 だから、114のような書き方ができるのです。 え?素直にnkfとかtr使うべきだって?ごめんちゃい。 tr -d \\r nkf -d 短いねえ…そして速そう… 正規表現にマッチした部分を全て置換し、その行を表示する awk 'gsub(/foo/,"bar")' sedで書くとこうか。 sed -n 's/foo/bar/gp' こういう処理はsedの方が楽に書けるのかな、うーん。 >>119 awk 'sub(/\r/,"")+1' 下はこの方が良かった。うっかりファイルの内容を消してしまいそうだ。 だいたい置換はsedで書いたほうが素直に読みやすいと思う 逆にそれ以外のツールでもスクリプトでもなく、awkで書きたくなるのはフィールドを使うものかな いや、しかし最近目から鱗落ちまくりです。沢山の書き込みに感謝感謝。 中身の検索はgrep 置換はsedとかtr 結合はcatとかpaste 計算はexprとか場合によりwc 多少組み合わせる必要があるならshでシェルスクリプトwhile、for、read、shiftみたいな 大抵やりたいことに対応するコマンドがある。awkでプログラム風に書くのは人を選ぶのかもね。 このスレが太古の昔に沈んでしまったのも、そのせいか。 実際、プログラム板にもあるけど、あちらはそこそこ書き込みがある。 Linuxも既にGUI全盛、バッチ処理もGUIでという流れか、シェルスクリプト総合スレもなくなってしまったし。 板全体がほとんど動作報告中心になって、Linuxやシステム全体のコアな部分、プログラミングの話題を 話す場所が消えてしまったような気がする。気がするだけ。 シェルスクリプトはUnix板で話せばいいしな Linuxでメジャーなシェルは大概BSDとかでも使えるし HTMLファイルからタイトル(title要素の持つ文字列)を取得する awk '/<title>/{ b=1 }; b{ s=s $0 RS }; /<\/title>/{ gsub(/.*<title>|<\/title>.*/,"",s); print s; exit }' 分かりやすさと効率を無視、短さを優先した別解。 awk '{ s=t=s $0 RS }; gsub(/.*<title>|<\/title>.*/,"",t)>1{ print t; exit }' どっかのスレにて、出遅れ、荒れ気味なので。 改行も保存してるけど、必要ないならRSを除けばいい。 perlの無いシステムでもawkはある!はず。 いつの間にかUnix板のシェルスクリプトスレまで無くなってやがる… ああ、そうだったのかー。でもまだ次スレ建ってないね。 スレ建てた事無いから分からないけど、最近建て難いようだし、そのせいかな。 112で諦めたgrepで空行を削除する処理の時間計測の結果。 time cat src.txt |grep . >/dev/null real 342m52.646s user 337m34.249s sys 0m7.174s grep -V GNU grep 2.6.3 寝て起きたら終わっていた。余程grepを必要とするときくらいしか、使うべきじゃない。 # 一つのケースでしかないのだけどね。ただ、これほど遅いとは… read.cgi ver 07.5.1 2024/04/28 Walang Kapalit ★ | Donguri System Team 5ちゃんねる