awk ファンクラブ
まだどうしてそういう結果になるのか…が全然解らないのですが 一つ一つひもといて自分のものにしていきたいです。 みなさん本当に色々ありがとうございます。 こういうのも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を必要とするときくらいしか、使うべきじゃない。 # 一つのケースでしかないのだけどね。ただ、これほど遅いとは… >>125 それ、xgawkで書くとどんなになるの? >>129 gawk '$0=gensub("</?title>", "", "g", RT)' RS='<title>.*</title>' IGNORECASE=1 >>128 待てよ…awkでもパターン検索だけなら遜色なく書けて かつawkのが速いんじゃ、grepの存在価値って… ああ、複数ファイルからの検索があるか つーても、これもawkでFILENAMEとFNR明示したら書けちゃうか… >>131 まあgrepで済む物は記述が簡単なわけで。 xgawkは使ってないなぁ。使ってる鳥には無いし。XHTMLが対象ならもっと短く書けるのだろうか。 >>130 おー!これはクール。 gawkは大文字小文字無視する処理書くの楽だね。流石だ。 >>131 前後の行を表示させたりが楽かも。まあ、滅多にお世話になることないけど… rm -r *でデータ飛ばしたから、そのサルベージに役立つとは…orz コマンド`grep -C N regex'を真似する awk 'BEGIN{ L=N; b=L+1; n=L+2; i=j=0; s=2 }; /regex/{ if (L&&s==1) print "--"; while (i!=j) { print a[i++]; if (i==b) i=0 } n=s=0 }; n>L{ a[j++]=$0; if (j==b) j=0; if (i==j) { i++; if (i==b) i=0; if (!s) s++ } next }; n++<=L' 書けた!!データ飛ばすは、アク禁に巻き込まれるは散々だった。よく見たら凄い遅レスだ… データのサルベージに使ったgrep -Cを書いてみた。流石にワンライナーとは言い難い。 効率はもう少し良くできそうだけど、これ以上短くするのは無理だった。実力が足りない;_; あまりに読み辛いので、pastebinに整形版を置いておきます。 ttp://pastebin.com/PJ2VfqN4 時間計測の結果を追記。 time grep -C 500 'public class\|jar cf\|javac\|\.java' <strings_a.txt >/dev/null real 0m2.112s user 0m1.528s sys 0m0.311s time awk 'BEGIN{ L=500;(略)}; /public class|jar cf|javac|\.java/{(略)}; n++<=L' <strings_a.txt >/dev/null real 1m20.089s user 1m15.426s sys 0m0.389s 一回計測。約50倍くらい遅いか。ネイティブとスクリプトだから、まあこうなる、と言ったところだと思う。 短い処理なら有利な場合もあるんだろうけど。 指定された正規表現を含むファイルの名前を表示する awk 'f!=FILENAME && /regex/{ print f=FILENAME }' gawkならこう書ける。 awk '/regex/{ print FILENAME; nextfile }' >>131 に近い。FNRも使って検索結果を表示するスクリプトも、あまり複雑にはならなそう。 下の方が速いけど、mawkだとnextfileをサポートしてなかった。 grep -lと同じ結果で、指定する正規表現によってawkの方が速く動くこともあるよ。 md5sumコマンドの出力から重複するMD5チェックサムを持つファイルを列挙する awk '{ i=++a[$1,0]; a[$1,i]=$0 }; END{ for (i in a) if (!k[split(i,k,SUBSEP)] && a[i]>1) for (j=1; j<=a[i]; j++) print a[k[1],j] }' まだ短く書けそうかな? あるディレクトリ以下を調べるなら、こんな感じでMD5チェックサムを計算する。 find sda6.photorec -type f -exec md5sum '{}' + この出力をパイプか何かで食わせればいい。 gawkの4.0が出たか。いろんな亜種を使う機会があるから、なかなか依存したプログラムは書けないね。 よく使うのはgawkとmawkだけど、皆何をよく使ってるのだろう?使用者が少ないから余計に気になる。 デバッガって使いやすい?いまだにprintで表示してやってるなぁ。 gdbやpythonデバッガやらと似てるのでとっつきやすくはあると思う。 fileコマンドの出力からテキストファイル(表示可能なファイル)だけ取得する awk '{ q=$1; $1="" }; /text/{ print q }' -F: FSは-Fオプションを使って1文字短く書く。使い方は次のようにパイプでつなぐ。 find sda6.photorec -type f -exec file '{}' + |awk '{ q="'\''" $1 "'\''"; $1="" }; /text/{ print q }' -F: |xargs -i cp -v "{}" sda6.photorec.text/ xargsに渡すためクォートしてる。ワンラインにシングルクォーテーション入ると書きづらい。 でも、こういう処理はawkが一番楽だね。 >>140 へー、それは良いね!って思ったけど自分が書くような短いスクリプトには不要かも… 今、awkでデバッガが重宝するような長いスクリプトって、どれほど書かれてるんだろう? >>142 BEGIN{for(;i<256;++i)c[t=sprintf("%c",i)]= i==32?"+":t~/[0-9A-Za-z]/?t:"%"sprintf("%x",i)} {for(s=i="";i++<length;s=s c[substr($0,i,1)]); print s} マルチバイト対応してて length() とか substr() とかが バイト数ではなく文字数を数えて動作するような小賢しい awk だと逆に動かない。 Gawk4.0の新オプションはそういう時のためにある訳か。 >>141 ファイル名には : も使えるから汎用じゃないね。 あとショートコードを意識してるようなのに不必要なセミコロンとカッコ内側のスペースが あるのはスタイルとして一貫してないな。 このスレ七夕に立ってたのか。3周年って言われると、まだ3年かと思ってしまう。 3年前といえばLLが盛り上がってた頃だから、もう少し前に立ってればここももっと盛り上がっていたかもね。 gawkは新しくなったけど、確実に他のLLに流れてるよなぁ… >>145 どこぞのOSでは使えない文字をわざわざファイル名に使わないよねって思い、楽してます。 ただパスに含まれる可能性はあるので、そういった場合は file -F; のようにして fileコマンドの使うセパレータを(使われていない)任意の文字に設定して下さい。 スタイルに関しては全くその通りで、自分でも冗長だと思いつつ残しています。以下言い訳… スペースは読み辛くなると思う所にだけ残すようにしています。また、ここに貼ると、 表示がプロポーショナルフォントになって、幅が狭い文字の隣から一部分コピペする操作をよくミスるため、 そういった幅の狭い文字(}とか;)の後には残しています。 ifやwhileの後、print $1 や "a" b "c" に含まれるものも省略できますが、違和感が物凄いので残しています。 セミコロンは(POSIXの仕様で)必要なものだけを残しているつもりです。 過去の互換性のために省略可能なものは、残すようにしています。 >>147 他のLLに比べて、Windowsで使われる頻度が滅法低いのも一因かなあと思う コマンドプロンプトで awk がやれることって、BEGIN{ } に何か書くぐらいしか無いのよね だったらPerlとかでいいじゃん、って話になっちゃう awkオンリーってのがムズイので、Cygwin上でsh他外部コマンドと組み合わせて使う事が多い 結局awkはプログラミング言語というより「ちょっとややこしいことも出来るUnix系テキストツール」としての性格が強いんだと思う。 そうか、Windowsでの使用率は考えたことなかったわ。そっちで今何が流行ってるのかは知らないけど、 GUI扱うライブラリを持つLLが使われてそうだ。こればかりは厳しい。そもそも、ライブラリって概念がないのが避けられてるのかな。 >>152 いやGUIはほとんどVisualStudio、Java、Delphi辺りで喰われてるよ その他のGUIツールもあるにはあるんだけど LLの主な出番は向こうでもテキストフィルタだったりはするんだけど Windowsにはそもそも組み合わせるような小物のコマンド群が無いから やりたい処理の1から10まで全部を1個(もしくは一連)のスクリプトで済ませるのが主流 だからたとえLLであっても、1言語で最初から最後までを完結できる大きめの言語が好まれるのよ awkは単品で使うより、組み合わせで威力を発揮する言語だからか、あまり使われない あ、いやテキストフィルタよりもCGIとかのWebでの出番のが多いか? awkでcgiも出来なくもないだろうけど、っていうかそれでblog作ろうとしてた人もいたな >>153 ホント?Delphiなんて懐かしいなぁ。GUIでなく、Webでの利用なら、もはやOSあまり関係ないような気も。よく分からん。 >>155 聞いたことはあるけど、見たことはない程度には珍しいかと。gawkはネットに対応してるから頑張ればサーバにもなれるかな? >>157 いやまあDelphiは新規としては瀕死で、過去遺産の保守で使われるのが主だけどね。 やっぱawkでcgiってマイナーか。しかしblogつーか、CMS作ろうとするのは凄いなw ちなみにgawkのhttpdって、どっかで見たなあ。 httプロトコルでなく、俺プロトコル用サーバならawkスクリプトでやってる。 httpに例えるなら、ファイルか404を返すだけの簡単なやつ。 しかもgawkのソケットでなく、inetdから呼ばれるだけの低機能。 私はエンバカになっても応援してるよ!>Delphi >>160 今更inetdって思ってて、ろくに調べてなかったけど、socatみたいな機能もあるんだね。 ポート監視→サーバ起動って機能しかないと思ってたよ。 これならネット非対応なawkでもhttpdくらい実装できる?…バイナリまともに扱えそうなのはgawkしかねー。 テキストオンリーまでなら何とかできそうだけど、画像も転送できないか。厳しい制限だ。 個人的にはawkは今まで通りシェルのお供でいいと思う perlとかでもそりゃ書けんことは無いが シェルのお供として使うには微妙に違和感あるんだよな〜 >>134 これを使って正規表現によって grep とどれだけ実行速度に差が出るのか計ってみた。 ttp://pastebin.com/bpXZ5pg8 数字だけではよく分からないので、ユーザ時間のグラフを描いた。 ttp://i53.tinypic.com/303a4iv.jpg 赤がawk、青がgrep こっちじゃないと見れないかも → ttp://tinypic.com/r/303a4iv/7 awk もばらつきがあるけど、grep ほどではない。 どちらも、マッチする可能性が高い正規表現は遅くなる傾向があるのかなぁ? 引数で与えられたファイルをメモリに読み込み繰り返し検索する awk 'BEGIN{f=ARGV[1];while((getline<f)>0)a[n++]=$0;close(f);ARGV=1};{for(i=0;i<n;++i)if(a[i]~$0)print a[i]}' 最近、用途が限られているもの中心だったので使えそうなワンライナーにしてみたよ。きっと。 指摘を受けたので、スペースは削ることにしました。ちっと見づらい? ↓は大文字小文字を無視するもの。こうするとdmesgの出力を何回も検索できる。 awk 'BEGIN{f=ARGV[1];while((getline<f)>0)l[n++]=tolower(a[+n]=$0);close(f);ARGC=1};{for(i=0;i<n;++i)if(l[i]~tolower($0))print a[i]}' <(dmesg) 長過ぎるone-linerを見易く改行するone-linerを書きなさい しまったー!書き込む前にちょろっと書き換えたところがバグってました。mawkで動きません。 >>164 の下のスクリプトは次に書き換えてください。 awk 'BEGIN{f=ARGV[1];while((getline<f)>0)a[n++]=$0;close(f);ARGC=1};{for(i=0;i<n;++i)if(tolower(a[i])~tolower($0))print a[i]}' awkのシーケンスポイントってC言語と同じなのかな…痛いミス。 おまけ。使ってるやつ。エスケープシーケンスを使って見つかった文字列に色を付けた。 awk 'BEGIN{f=ARGV[1];while((getline<f)>0)a[n++]=$0;close(f);ARGC=1}; {for(i=j=0;i<n;++i)if(k=match(tolower(a[i]),tolower($0)))print C(j=!j)I(I(a[i],C(39),k+RLENGTH),C(31),k);print C()}; function C(n){return"\033["n"m"};function I(x,y,z){return substr(x,1,z-1)y substr(x,z)}' パターンごとに改行を入れた。少し見やすいか? >>164 の上のスクリプトに色を付ける機能を追加。ずっと分かりやすいと思う。 awk 'BEGIN{f=ARGV[1];while((getline<f)>0)a[n++]=$0;close(f);ARGC=1}; {for(i=j=0;i<n;++i){l=a[i];if(sub($0,C(31)"&"C(39),l))print C(j=!j)l}print C()}; function C(n){return"\033["n"m"}' subをgsubにするとマッチする全ての文字列に色を付けられるよ。 gawkならgensub使ってもう少し短く書けるかもしれない。IGNORECASE=1で簡単に大文字小文字無視できるし。 classは使えるようになりましたか? > gawk4 つ ttp://awk.info/?doc/dsl/awkplusplus.html ふるいけや "かわず とびこむ" みずのおと といったレコードを、 field[1]=ふるいけや field[2]=かわず とびこむ field[3]=みずのおと number_of_field = 3 とフィールド分割するすっりした方法を教えて下さい。 >>172 それ、CSVとかでもよく語られることだけど、意外と面倒なのよ。 例えば「"」自体を文字列に入れたい場合はどうするのか、とか色々決めなきゃならんし。 あれ?awkでclass使いたいって事なんでしょ? ttp://ja.wikibooks.org/wiki/AWK%2B%2B%E3%81%AB%E3%82%88%E3%82%8B%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E5%85%A5%E9%96%80 >172 素直に区切り文字を変えるしか... ふるいけや,かわず とびこむ,みずのおと FS="," 自己レスです。 BEGIN { FPAT = "([^" FS "]+)|(\"[^\"]+\")" } みたいな事をしました。 awk にわけわかんな機能を増やすよりも、 RFC4180 互換なフィールド分割オプションを実装すればいいのにといつも思う。 perl -e 'print $1 if /href="(¥d¥d¥d¥d-¥d¥d¥-¥d¥d)"/' と同じことをawkでやろうとしているのですがわかりません。 awk -e '/href="(¥d¥d¥d¥d-¥d¥d¥-¥d¥d)"/ { print ??? }' グルーピングしたあとにそれを取り出す方法を探したのですが、わかりませんでした。 awkまたはsedでのやり方を教えて下さい。 >>181 馬鹿じゃないあなたに是非>>182 の回答をしてもらおうか。 >>182 perl がわからないから求めるものがよくわからないけれど、こんな感じ? awk '/href=\"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\"/ {print $1}' input.html awk '/href=\"\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)\"/ {print $1}' input.html BEGIN とか使ったほうがいいのかもしれないけれど awk '/href=\"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\"/ {print $1} BEGIN { 何か書く }' input.html >>182 どのawk使っているか分からないし、入力の仕様も分からないけど、どこでも動くのはこんな感じ awk -F\" '/href=/ { for (i=1; i<=NF; i++) if ($i ~ /href=$/ && $(i+1) ~ /[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/) print $++i }' gawkでも正規表現パターンのグループを保存している組み込み変数はなかった気がする gawk4.0なら awk '{if (match($0,"href=([0-9]{4}-[0-9][0-9]-[0-9][0-9])",a)) print a[1]}' じゃ駄目? ごめん、 awk '{if (match($0,"href=\"([0-9]{4}-[0-9][0-9]-[0-9][0-9])\"",a)) print a[1]}' >>184-186 うーん、あまりわかりやすい方法ではないですね。 メンテナンスしにくいコードになってしまうので、perlが使えるよう上司に交渉したほうがよさそうです。 回答いただいた方、ありがとうございました。 >>185 はともかく>>186-187 の方がPerlみたいにグローバル変数にマッチ結果を入れるより分かりやすいと思うのって俺だけ? >>189 186は、単にgawk独自の拡張機能を知ってないとわかりにくいというだけであり、 マッチした結果を明示的に変数に代入するのはいいことだと思います。 なお個人的には match(string, rexp, matched) はmatchedがいわゆるout変数になるため分かりにくいです。 matched = match(string, rexp) のほうがよかったです。 >>190 何言っているのかちょっと分からん。言語仕様上awkは配列を返せないだろ gawk独自の実装はどうも…という話がよく出てくるけど、 gawk/mawk/true awk相互で運用する必要ってよくあるものなの? またはbusyboxのawkで使いたいとか? gawkは最早awkと呼ぶには拡張され過ぎている感じがある よくあるかは知らないけど、少なくとも手元の環境には3種類のawkがあって、gawkの拡張が使えない mawkはnextfileにも対応してないし、awkは実装の差がかなり大きいと思うよ gawkが拡張されてるのは承知だが、gawk依存だとメンテが大変だから perlというロジックが分かりにくい。 gawkで (ああ(いい((うう)(ええ)))) この行の「ああ」「いい」「うう」「ええ」を変数に入れたい時、 何か定番な書き方はありますか? 何を期待しているのか分からん 括弧を区切りにして分けたいだけならFS="[()]+"で 配列に入れたいならsplitでどう? もしかして括弧の対応をとりながら分けたいってことなら gawkに詳しい別の誰かに期待してくれ。拡張正規表現でも無理じゃなかったか str = "(ああ(いい((うう)(ええ))))" while (match(str,/([^()]*)/)) { v = substr(str,RSTART+1,RLENGTH-2) str = substr(str,1,RSTART-1) substr(str,RSTART+RLENGTH) if (v != "") { # 取り出した v をなんかする } } とかじゃ駄目なの? ちゃんと構文解析するなら yacc (bison) を使わないと駄目だよ _ |O\ | \ キリキリ ∧|∧ \ キリキリ ググゥ>(;⌒ヽ \ ∪ | (~) ∪∪ γ´⌒`ヽ ) ) {i:i:i:i:i:i:i:i:} ( ( ( ´・ω・)、 (O ⌒ )O ⊂_)∪ しつもん http://gauc.no-ip.org/awk-users-jp/blis.cgi/DoukakuAWK_050 のスクリプトの35行目 for (++day;;) { の意味と動作がよくわからんです which で等価なループを書くとどんな感じになるの? カコイイ先輩おしえてplz >>201 先輩ありがとう ++day を最初に持ってくるのはオイラも考えたんですが、break の条件式も反転して持ってくればおkかなと思って $ diff time.awk time2.awk 34,35c34,35 < < for (++day;;) { --- > ++day; > while (day >= year_days) { 49,52d48 < } < < if (day < year_days) { < break; てやったら1日ズレちゃったんだけどこれってどこがマズいんでしょうか (・ω・` ) >>202 そのbreakの後にも続きの処理があるだろ。年もズレるんじゃない? >>203 day の値を追っかけてみたら元のfor、変更後のwhileともに同じ値で終了してたので頭抱えてたんですが もう少し調べてみたら leap の値がズレてました break の前の処理が1回分少なかったということで、落ち着いて考えれば当たり前の結論でした (;´Д`) 結局この処理の場合は元々のスクリプトや >>201 のように無限ループ使うのが一番シンプルに 書けるんだなーと確認して納得しました。先輩方ありがとう AWKを256倍使うための本が読みたいのですが どうにかして入手できないでしょうか? たけえわ! こういう本こそ電子版にしてくれねえかなあ レスありがとうございます 高いけどあるといえばあるんですね どうしようかな 長年親しんだテキストの遊園地がなくなってて非常に悲しい どっかにアーカイブないっすか >>215 で、それはいつできるんだ? できたらURL貼るのを忘れんなよ おばんです。 Linux環境の方にお願いします。 下記にあるblength()を試してもらえませんか? http://www1.bbiq.jp/rem_vba/gawk_blength.html よろしくお願いします。 HP製作者です。当方の環境はWindowsです。 Linux環境下で同じ実行結果を得ることができるのか、 知りたいのです。 よろしくお願いします。 それもそうですね。 昔々REDHATだったか入れていました。 現在のおすすめのディストリビューションは何でしょうか? 今はMS製のcygwinみたいのがあるのでは。Windows 10 Bashナントカ Windows 10 Creators UpdateでUbuntu 16.04.1 これかな。 やってみます。ありがとうございました。 jgawkをガウォークって読んでたマクロスヲタいない 誰でも簡単にパソコン1台で稼げる方法など 参考までに、 ⇒ 『宮本のゴウリエセレレ』 というブログで見ることができるらしいです。 グーグル検索⇒『宮本のゴウリエセレレ』 DCQTVO9E2N 空の配列はどう作るの。 bashの declare -a var 相当。 僕の知り合いの知り合いができた副業情報ドットコム 関心がある人だけ見てください。 グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』 V09DR Linux Beep Musicに感動したのでnokia2beeps.tclを移植してみた https://pastebin.com/hLJnpPNv nokia2beeps.awkとか保存し下記のページのコードを鳴らすやつ http://nokia.nigelcoldwell.co.uk/tunes.html あと日本語の着メロも対応してる(コメント参照) awk だけど実行ファイルのフォーマットは ELF …いや、なんでもないです。 初心者ですが正規表現で半角をすべてというのはどうやるんでしたっけ どっかで見たような気がするんですが >>227 Awk の識別しは、最初っから空の配列だよ いきなり使えば良い みなさんはgawk以外の処理系に移植できるか とか、多少でも考えますか?私は気にしなくなりました。 他にも幾つか実装があるにはあるんですが、あんまり 活発じゃないし、言及もされないし、こだわりすぎると 不便でしょうがないから、気にしなくなりました。 けしからんでしょうか? GNU awkが事実上標準だからPOSIX準拠は気にしないな GNU AWK 5.0がリリース。8年ぶりのメジャーバージョンアップ。正規表現ライブラリが GLIBCからGNULIBへ移行、名前空間が実装 2019年4月17日 https://www.publickey1.jp/blog/19/gnu_awk_508glibcgnulib.html UnixやLinuxにおいてsedやgrepなどと並んでよく知られているツールの1つがawk(オーク) です。このawkのGNUプロジェクトによる実装の最新版「GNU AWK 5.0」(gawk 5.0)の リリースが発表されました。 2011年にリリースされたGNU AWK 4.0から8年ぶり、直前のバージョンでとして2017年10月に リリースされた4.2.0からは約1年半ぶりとなります。 AWKはいわゆるスクリプティング言語の一種。変数や関数、制御文など基本的な構文を備え、 テキストファイルを効率的に処理できるのが特徴です。 GNU AWK 5.0の新機能としては、printfの%aおよび%Aの書式がPOSIX標準に準拠したこと、 正規表現のルーチンが、長年にわたってメンテナンスされてきたGLIBCからGNULIBに 置き換わったことなど。 また、識別子に非英語文字を使うためのドキュメント化されていなかったオプションなどは 削除され、ソースコードはC99環境が想定されるようになっています。 そして新たに名前空間が実装されています(詳細はマニュアルを参照とのこと)。 名前空間って、これまでのスクリプトが動かなくなるんだべか。 さすがにそれは無かった。 $ gawk --version GNU Awk 5.0.0, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2) : $ gawk 'BEGIN{print awk::ARGC}' 1 $ gawk 'BEGIN{print ARGC}' 1 $ gawkでキーボードから一文字入力をしたいんですが、何かいい方法ないでしょうか? stdinをgetlineするのではなく、キーを何か一つ押したときにそのコードを即座にgawkで受け取りたいんです。 具体的に何がしたいのかというと、BEGIN内部でスクリプトの動作を設定するパラメタをキーボードで指示したいんですが、 その支持を矢印キーでメニュー選択させたいんです。 ターミナルのエスケープシーケンスはVT100環境を想定しています。 何かヒントでもいいので一文字入力の方法を教えてください〜 gawkはこれ使ってます。 GNU Awk 4.2.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2) 追記 gawkを動かす環境はubuntu19.04で、主にWindowsからteratermでsshログインしての使用を考えています。 >>241 awkじゃなきゃあかんの? cursesでやればいいと思うけど >>243 awkでやりたいんですよ。 cursesってawk用ライブラリありましたっけ? 自分アホなりに色々調べて、"read -n 1" をうまく使えば文字コード取れそうという所までは気がついたんですが、 これをawkスクリプト中で実行させて戻り値をawk変数に取り込む方法がわかりません。 どうすれば文字コードが取れるんでしょう? 試さないで適当に書いてみるけど 一文字読みとる command 用意して command | getline var もしくは入力された文字を終了ステータスとして返す command で var = system(command) >>244 確かにそれはちゃんと機能する。しかし、矢印キーとなると話は別だ。 矢印キーは 3 バイトだから。 1 バイト読んで ESC だったらもっと読むということになる。 もちろん ESC じゃなかった場合のことも考える。 想定した処理が全部終わった後で、印字可能文字で 1 行で出力する …というプログラムを C で書くということになるかなあ。 ところでエコーバックはどうする? 多分、こんなこともしたくなるんじゃないか。 https://qiita.com/Ki4mTaria/items/36feda5f6aa54643775a dialog とか使った方がいいんじゃないかな。 なんかすみません。 dialog & shell & awkでできるのはわかってるんですが、なんか負けたような気がしてw なんとかshellのコマンドか標準で入っている外部コマンド & awkでできないもんかと思ったんです。 Linux ←→ Windowsのポータビリティを考えた場合、やはり1文字入力してそれを返すだけの小さなプログラムをCで作ってawkでそれを呼んで戻り値を得るのが一番手っ取り早いのかな、と思いつつあるところです。 でも、もう少し最初の路線で調べてみます。徒労に終わりそうな気はしますが。 bash でも出来なくはないと思う。読むだけならいくらでも出来る。 しかし、「残さず食べる」ということを考えると read -n はちょっと… なぜこれを考える必要があるかというと、食べ残しがあるとたとえばシェルの場合なら それをコマンドラインだと思って読んでしまっだりする。 read -n は食べ残しが無かったら入力待ちになってしまうので適していないと思う。 他人に使わせるプログラムなら常に意識しておくべきことかもしれない。 そこで、まだ試してないならこんなことを試してみてほしい。 BEGIN { cmd = "bash -c 'TMOUT=5 ; read -N 8 v ; echo \"$v\" ;'" for( i = 0; i < 8; i++){ while ( 0 < ( cmd | getline)){ print "i=" i ", 0=[" $0 "]" } close( cmd) } } 得られたデータの長さが指定した長さに達していないならタイムアウトで終了した。 つまり、食べ残しは無いということになると思う。 ただし、改行の扱いがめんどくさい。 bash は read で読んだ改行をちゃんと送っているのだが getline が削除してしまう。 そして最後の改行は echo が加えたもので、read で読んだのではない。 awk の方で RS の値を変えることでめんどくささが減る可能性はある。 しかしやはり最終結果だけを 1 行で受け取るほうがいいかもしれない。 もっとも、入力元を共有しているから食べ残しが問題になるのであって 新たに端末エミュレータを起動してその上で実行するのなら問題にならない。 パイプが繋がらないから別の方法で結果を返す必要はあるが、メニューを出して ユーザに選択させるという用途なら悪くない方法かもしれない。 そもそも「リターンキーで決定」とかなら食べ残しの心配は無いかな? ありがとうございます。 -Nオプションでタイムアウト指定をするというのは目からウロコでした。 秒数を1にして、できるだけレスポンスのいい動きをさせようと思います。 矢印キーは3文字、Fnキーは5文字になるんですね。 そんなことも知りませんでした(汗 今日はawkにはpythonやperlにはあるord関数とchr関数が無いことを知って愕然としてました(笑) 文字を受け取ったはいいものの、文字コードをどうやって調べようかと悩んで行き着いた先のコードです。 笑ってやってください。 function ctblmake(ctbl) { for (i = 0; i < 255; i++) { ctbl = ctbl sprintf("%c", i); } return ctbl; } function ordhex(c) { return sprintf("%02x", index(ctbl, c)-1); } BEGIN { ctbl = ""; ctbl = ctblmake(ctbl); print ordhex("?"); print ordhex("c"); print ordhex("b"); } 今日はもう寝ます perlとかでやれよ。 awkで簡単に出来ることをsed+grepで頑張る人達がクダスレ辺りに沢山いるが、それと同等だろう。 知恵の輪としては面白いけれど、成果には乏しいのでないか。 なんか、返事するのがアホくさくなってきました。 さようなら。 awkはまずデータファイルありきで便利なものだしねえ。 趣味でどういう使い方しても勝手だけど。 >>254 Perl を知っていながら awk でやろうってんだから、この程度のことは予想できたでしょう。 無視してりゃいいんだよ。 もっとも、真剣に取り組んでいるなら他の場所を探してもいいかもしれない。 でもここにも君を助けようとした者がいたことは覚えておいてほしい。 あっ、某知恵袋はやめときなさい。あそこは知ったかぶりが多いから。 知らないなら回答しなきゃいいのにね。 >>257 Linuxオタが集う外国の掲示板当たりの良いのかもな 普通のLinuxユーザーなら、awkにこだわりすぎの変な奴だになって 相手にしてはいけない・からかってやれだろうからな。 >>249 bashはreadline組み込まれてるので使って良いんじゃないかな? あとライン毎にバッファしてるのが問題な気がするから、stdbuf cmdでcmdの参照してるstdlibをすり替えられて、一文字毎にflushする用に出来たりするがどうだろう busyboxのお陰でやっとwindowsでawkを使う気になれた やっぱり良いツールだな winget install awkで入る(g)awkじゃいかんの? 今のところ困った事はない 他のunixコマンドと連携して使いたかった そこでいつもやる気なくしてた chocoやら乱立してたパッケマネがやっとMS公認の下で統合されたことだし、整合性も良くなってくんじゃないの 楽観的予測 こんにちはPOSIX原理主義者です。何か質問ある? 今のところ使用上困ってることは無いんだけどせっかくなのでひとつ質問を nawk, mawk, gawk どれが最もPOSIX準拠? 出来れば標準的なやつで修行しておきたいので >>266 全部POSIX準拠。ただし全部POSIXに準拠してないところがある。 本来の文字列整形だけなら3つともあまり変わらん気がするけど 出過ぎた事を言わない方がいいんだろうな 全部POSIX準拠だけど、Unicodeに対応してるのはgawkだけで lengthの長さが違うとかいう違いがある。 そもそもPOSIXはCロケールしか考慮されてないので Unicode非対応でもPOSIX準拠。 >>260 busyboxで日本語つーかunicode対応してるのあんの? 見たことないけど >>260 busyboxの貧相な実装に頼らなくても、そもそもwindowsはパッケージマネージャにマトモなawk(たぶんgawk)入ってなかったか? winget install awk とかそんな感じのコマンドで一発 あとpwshで定義できるfilterプロシージャがBEGIN/ENDとかまんまawk丸パクりな事に気付いてわろた read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる