X



awkについて語るスレ $2
レス数が900を超えています。1000を超えると表示できなくなるよ。
0001デフォルトの名無しさん
垢版 |
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/
0829デフォルトの名無しさん
垢版 |
2016/09/27(火) 19:26:43.05ID:Icjzq3KF
だめというか、見つけられなかった。
ただでさえ Windows のことなんか知らないんだからこれ以上無理。
いい方法を知ってたら教えてあげて。
0830デフォルトの名無しさん
垢版 |
2016/09/27(火) 19:51:11.26ID:Icjzq3KF
Cygwin は試してみたけどインストーラに丁重にお断りされたよ。
0831822
垢版 |
2016/09/27(火) 23:10:22.59ID:eGFFwbsN
たくさんの情報ありがとうございます。現状でWindowsに拘るなら、Bruce版3.1.7を継続して
使用するか、Cygwin版に乗り換えるか、Windows Subsystem for Linuxで動作させるかの
いずれかになりそうですね。

CygwinやWindows7でのWindows Subsystem for Linuxは、どちらも別途インストールが必要
とのことなので、職場の自PCはともかくスクリプト配布先に(スクリプトを動かすためだけに)
導入してもらわないといけないのはちょっと難しそうです。
Cygwinの導入状況とWindows10への切り替え時期の様子を見つつ、しばらくBruce版3.1.7を
使うことにします。
0832デフォルトの名無しさん
垢版 |
2016/09/28(水) 07:26:06.87ID:6NcLFLen
実は方法が無いわけではない。シングルバイトモードならできる。でも本当にやりたい?
本当に真剣に必要としているなら、このスクリプトでテスト3をやってみてほしい。

{
  c = "[\\000-\\177]|[\\340-\\357][\\200-\\277][\\200-\\277]"
#  print( length($0));
  str = $0; print( gsub( c,"0",str));
  print;
  sub(/<tag>/, "");
  sub(/<\/tag>/, "");
  sub(/hello/, "ABC");
#  sub(/.う/, "U");
  sub( sprintf("(%s)う",c),"U")
  print;
}
0833デフォルトの名無しさん
垢版 |
2016/10/01(土) 22:37:26.49ID:apxhHWta
やっぱり klabaster gawk はよく解らない。

$cat u2.awk
{
  print( length($0))
  sub(/う/, "U")
  print;
}
$LANG=C wine ../gawk64.exe -f u2.awk u2.txt > /dev/null
$LANG=ja_JP.EUC-JP wine ../gawk64.exe -f u2.awk u2.txt > /dev/null
$LANG=ja_JP.UTF-8 wine ../gawk64.exe -f u2.awk u2.txt > /dev/null
gawk64: u2.awk:3: sub(//, "U")
gawk64: u2.awk:3: ^ unterminated regexp
gawk64: u2.awk:4: sub(//, "U")
gawk64: u2.awk:4: ^ unexpected newline or end of string
$

UTF-8 で「う」は 3 バイトだから、シフトJISで解釈した結果
その後ろの / もマルチバイト文字の一部になるのだろうか。
いや、UTF-8 で解釈してくれないことに文句を言いたいんじゃないんだ。
UTF-8 で書いてあるのになぜ LANG=ja_JP.UTF-8 の時だけエラーになるのだろう。
0835デフォルトの名無しさん
垢版 |
2016/10/08(土) 21:51:54.06ID:66+5bUgM
>>749からのレスで、$が演算子だったの? というようなところが気になって
少し調べてみた(調べたというほどの作業はしてないか)。

まず書籍。手持ちの数冊で確認。
『プログラミング言語AWK』(トッパン 初版第7刷)
さいごのまとめで演算子一覧に記載。本文中(p8)では「欄は常に$1,$2のように
参照しなくてはいけないと思われているかもしれないが、実は$のあとには,欄の
番号を指し示すための任意の式を書いてもよい」と書かれている。また、p46には
「欄変数」の項に「入力行の欄(field)は,$1,$2から始まって,$NFという名で呼ばれる」
との記述がある。

『sed & awk プログラミング』(アスキー出版局 初版)
旧版。本文中(p212)で「フィールドを参照したいときには、フィールド演算子$を使えばよい」
また(p217)で「フィールドを参照するにはドル記号($)演算子を使う」、Appendix(p471)で
「それぞれのフィールドは、$1ならば最初のフィールドの値を参照し、」と表現されている。
Appendixの演算子一覧に記載。

『AWKを256倍使うための本』(アスキー出版局 初版)
Appendixで演算子一覧に記載されているが、本文(p65)で「分解された各フィールドは、
$nという変数(nは、始めのフィールドから順に1,2,3...となる。もちろん即値の代わりに変数を
指定することも可能だ)でアクセスすることができる」とある。他の箇所でも$n変数と書いてある
ところがある。p66で「各フィールドを表す$nであるが、なぜこんな名前になっているかご存じだろうか?
実はこれもUNIX文化からきているのだ。UNIXの代表的なシェルであるshやcsh(最近ではkshや
tcshかな?)のシェルスクリプトのなかでコマンドラインパラメータを表す変数として$nが使用されて
おり(中略)これにあわせてawkで$nが使用されているようなのである」と書いてある。

『AWK実践入門』(技術評論社 初版)
>>766にあるように特別な変数として扱われており、リファレンスにも$が演算子で
あることの記載がない。
(続く)
0836835
垢版 |
2016/10/08(土) 22:00:44.45ID:66+5bUgM
(続き)
ネットの情報。2016.10.8現在。
Gnu Awk ユーザーズガイド/The GAWK Manual/Effective AWK Programming
gawkの解説書。バージョン違いがあるようだが、翻訳版で目に留まったもの。
「定数でないフィールド番号」の項で「あるフィールドを参照するために、awk言語での任意の式を
`$'の後で使うことができる」と記述されている。「演算子の優先順位」の項では演算子として
並べられている。

man gawk
翻訳版、リナックスコマンドというサイト(www.linux-cmd.com)から。
「入力レコード中の各フィールドの値は、左から $1, $2 等という名前で参照できます。
$0 はレコード全体です。フィールドに値を代入することもできます。フィールドは定数だけでなく、
変数によって参照することもできます。」となっている。演算子のところに記載あり。

AWK Users JP
サイト中「awk 基礎文法最速マスター」のページで「特殊変数」の項に$0,$1〜$NFの説明。
フィールド参照の語はない。また、リファレンス的な演算子のまとめはない(?)。
ページ上部に「この文書は書きかけです」とあるので、未整備ということだろうか。

IBM Knowledge Center
awkコマンドのページ(www.ibm.com/support/knowledgecenter/ja/ssw_aix_71/
com.ibm.aix.cmds1/awk.htm)では「レコードとフィールドによるファイル処理」の項で
「各フィールドはフィールド変数によって参照されます。レコードの最初のフィールドには $1 変数、
2 番目のフィールドには $2 変数というように、変数が割り当てられます。」との記述。少しうしろの
方、「フィールド変数」の項でも「フィールド変数は、$ (ドル記号) とそれに続く数値または数値式で
指定します。」とある。$が演算子であることの記載はない。

てな感じで、『プログラミング言語AWK』でも「欄変数」という表現があり、誤解しそうな感じはする。
また、256倍本に書いてあるようにシェルスクリプト中のパラメータとして$nがあることから、$nが
(特別な)変数として認識されてしまっているのではないか、とも想像する。個人サイトのawkの解説
ページでは、$nという変数にフィールドが代入されると説明しているところもあった。そのように理解して
スクリプトを書いてもさして不都合はないだろうな、とは思うが。
0837デフォルトの名無しさん
垢版 |
2016/10/08(土) 23:11:50.50ID:ZMh6U7O9
広範な調査乙。Gawkのrefcardでもちゃんとoperatorに含まれているなあ。
演算子と明確に認識していなくても、$の後に式OKと思っていれば差し支えなさそう。
0838デフォルトの名無しさん
垢版 |
2016/10/18(火) 23:10:18.54ID:TQpGgbw6
gawk4で関数ポインタみたいなもんが追加されましたけど、これlengthとかsubstrの
組込み関数や@loadした自作dllの関数とかにも使えるんですね
案外便利かも

@load "hage.dll"
 BEGIN{
 kumi = "length"
 func = "hagefunc"
 ng[1] = "substr"
 print @kumi("ABC")
 print @func("彡 ⌒ ミ ")
 print @ng[1]("XYZ", 1, 1) # 配列越しに呼ぼうとしたらsyntax error・・・残念
}
0839デフォルトの名無しさん
垢版 |
2016/10/21(金) 17:10:59.85ID:MQQBNMPM
>>756
こういう過疎スレで無駄に突っかかってくるやつむかつくんだが死ね
0843C初心者
垢版 |
2017/02/28(火) 13:18:15.09ID:Mb8mQo1M
awkスクリプトをCソースに変換してコンパイルするための「awka」というツールでできるだけ簡単にUTF−8サポートさせる方法を知りたいです。
ネットで散々調べましたがないようです?
0846デフォルトの名無しさん
垢版 |
2017/03/05(日) 14:45:26.28ID:KmKKYedf
gawkに対応してるなら大丈夫ってことかな?
asciiしか考えていないなら、ソース全チェック…。
要するに、日本語化するんだろうけど。

全然別の言語変換にちょっと咬んだことがあるんだけど、
製品化しちゃってからダブルバイト考慮してないことがわかって、かなり面倒だった。

とりあえず変換してから、ソース見て直すほうが早かったり(笑

がんばってね。
0847デフォルトの名無しさん
垢版 |
2017/03/06(月) 11:39:31.22ID:FdaYmB9f
awkで $1,$2...$6 こんな出力を↓下にしたいんだけど どうすればいいですかね?
470230
470290

002347
002479
0848デフォルトの名無しさん
垢版 |
2017/03/06(月) 12:33:46.83ID:FW5jfGh1
GNU awk の asort() を使うとか。

printf '470230\n470290\n' |
gawk -vFS= -vOFS= '{
for(i=1;i<=NF;i++){
arr[i]=$i
};
asort(arr);
for(i=1;i<=NF;i++){
$i=arr[i]
};
print
}'
0849デフォルトの名無しさん
垢版 |
2017/03/06(月) 15:19:43.83ID:FdaYmB9f
ありがとう
gawk いれないでなんとかならないかな
0850デフォルトの名無しさん
垢版 |
2017/03/06(月) 17:28:40.15ID:FW5jfGh1
う〜ん、そうなると awk を使わなくてもいいかな

printf '470230\n470290\n' |
while read -r n
do
echo "$n" | grep -o . | sort -n | tr -d '\n'; echo
done
0851デフォルトの名無しさん
垢版 |
2017/03/06(月) 19:23:27.89ID:08XsJPyW
>>840
だからブーメランとかそういうの関係ないから死ねって言ってんだろカス
死ね
0852デフォルトの名無しさん
垢版 |
2017/03/06(月) 19:24:30.15ID:08XsJPyW
>>844
粘着が10年位延命しても何もすごくねえよ
突っかかってきたぶちころすぞ雑魚死ね>>840
0853デフォルトの名無しさん
垢版 |
2017/03/06(月) 19:26:33.18ID:08XsJPyW
>>840
ブーメランとかじゃなくて死ねって言ってんだから死ねボケ
0855デフォルトの名無しさん
垢版 |
2017/03/09(木) 21:48:39.65ID:0T9qj2kA
連想配列で
echo '470230' | awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++){a[$i]++}for(i=0;i<=9;i++){for(j=1;j<=a[i];j++){printf("%s", i)}}printf("\n")}'
002347
0856デフォルトの名無しさん
垢版 |
2017/03/10(金) 00:18:57.87ID:+B1nKlhG
既に否定されているがgawk4がもし使えたら
awk '{ORS="";PROCINFO["sorted_in"]="@val_num_asc";x=split($0,a,"");for (i in a)print a[i];print "\n"}'
0857デフォルトの名無しさん
垢版 |
2017/03/10(金) 04:05:38.25ID:wGo6zQ56
最近の gawk ならインクルードファイルが用意されてて join とか使えたり

gawk -vFS= -vOFS= -i join.awk '{split($0,a,"");asort(a);print join(a,1,length(a),SUBSEP)}'
0858デフォルトの名無しさん
垢版 |
2017/04/04(火) 22:35:43.00ID:9/WMFGSO
# gawk4の読込みタイムアウト機能、けっこう便利そう・・・だけどWindowsはCygwin版じゃないと使えない。残念無念。
BEGIN{
  PROCINFO["/dev/stdin", "READ_TIMEOUT"] = 180000
  print "3分間待ってやる"
  getline t < "/dev/stdin"
  if (t=="バルス") {
    print "ああ…ああ…目があぁぁぁぁぁ〜!"
  }
  else {
    print "時間だ!答えを訊こう!"
  }
}
0859デフォルトの名無しさん
垢版 |
2017/09/16(土) 00:02:08.63ID:lO9EtkAG
自作の読込みパーサextensionでgz形式のファイルを食えるようにしてみたけど
パーサは一度にひとつしかロードできない設計らしく(ソースでそうなってた)
同じ読込みパーサ形式のxmlライブラリとは併用できなかった
ちょっと使いにくいなあ・・・
0860デフォルトの名無しさん
垢版 |
2017/10/09(月) 16:41:58.59ID:7/rU/a8H
4.2.0Betaあげ
0861デフォルトの名無しさん
垢版 |
2017/10/16(月) 14:34:21.07ID:tJ1aGDYb
ファイルの終端関係の謎のエラーに直面
「何で行末が欠ける?分からん、全然分からんぞ!」
と悶えていたら、
いつの間にかvimの設定が変になっていて、
書いたファイルがデフォで行末に\rが来る
ようになっていた。
brew でインストールvimインストールしたとき
妙な設定になったのか?

いやねawkのスクリプトで、
空フィールドが\rになったりとか
macOSなのに変だなあと思っていたのだが…
システム外vim使うときは要注意か。
0864デフォルトの名無しさん
垢版 |
2017/10/22(日) 23:26:23.47ID:/qEHJ0vm
>>756
普段話題なく3年も続こうがべつにすごくないね
0865デフォルトの名無しさん
垢版 |
2017/12/09(土) 10:00:30.84ID:/kecouyU
BEGIN{for(i=1;i<=10000000;i++){printf "%08d", i > "test" } close("test)} の実行にかかる時間を
4.1.4と4.2.0で比較すると、4.2.0のほうが倍近く速くなってるね
fwriteのロックがどうたらの影響なんだろうけど
0866デフォルトの名無しさん
垢版 |
2017/12/12(火) 21:01:15.07ID:zxiueT/o
懐かしいなぁ。
AWKは自由に現実的な限度はあるけど、書いてて楽しい言語だった。
0867デフォルトの名無しさん
垢版 |
2018/01/08(月) 11:00:30.57ID:szpKYJOz
お疲れ様でした
0868デフォルトの名無しさん
垢版 |
2018/01/12(金) 00:18:25.22ID:8Bbkgawk
IDがgawkなので来ました
0870デフォルトの名無しさん
垢版 |
2018/01/17(水) 17:52:56.47ID:MoHAEd1l
置換函数の第二仮引数に[バックスペース][置換対象の文字列]みたいにしたい時は
gsub(/foo/, "\\\\&", $n)
ってしないといけないんだね。
gsub(/foo/, "\\bar", $n)
が foo -> \bar だったんで foo -> \foo は
gsub(/foo/, "\\&", $n)
でいいと思って半時程嵌った。
0872デフォルトの名無しさん
垢版 |
2018/03/09(金) 13:30:21.59ID:Yd19z7Tx
ある行に 20 と 34 とはいってる
この行ごと除外したいけど・・・
 
0874デフォルトの名無しさん
垢版 |
2018/03/09(金) 21:38:00.87ID:3i0y1Him
こうかな
gawk "$0!~/20|34/{print}"
0875デフォルトの名無しさん
垢版 |
2018/03/09(金) 23:45:36.30ID:Ejthnyow
AWK プログラムの基本構造となっている「パターンとアクションの対」のうち、
アクションが省略されている場合は入力行がそのまま出力される。
またパターンが単一の正規表現である場合は、その正規表現と $0 との照合が行われる。

gawk '!/20と34/'
gawk '!/20|34/'
0876デフォルトの名無しさん
垢版 |
2018/03/10(土) 21:39:17.88ID:NqpdHf3N
こぴぺしてやってみたけど 両方消えちゃうんだよね

20 と 34があった場合 出力しない
片方でもあれば 出力する

awk '!/01 / && !/03 /'  これも両方消えてる・・
0878デフォルトの名無しさん
垢版 |
2018/03/11(日) 10:58:35.24ID:tN+YLJlR
ありがとう 
()はきがつかなかった・・
0879デフォルトの名無しさん
垢版 |
2018/05/23(水) 20:10:48.40ID:Au5e7VGg
僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』

0VDE5
0880デフォルトの名無しさん
垢版 |
2018/06/08(金) 22:00:41.48ID:W8HYHVfd
split関数より$0へ代入したほうが速いage
0881デフォルトの名無しさん
垢版 |
2018/07/04(水) 22:29:02.55ID:gFgZc5FG
02P
0884デフォルトの名無しさん
垢版 |
2018/12/02(日) 13:44:27.64ID:jISJOvCb
AWKって重いと勝手に思ってたけど下手にシェルで制御構文作るより早いね
尤もWSLでやってるのでforkの時間とかそういう問題かもしれないが。
0885デフォルトの名無しさん
垢版 |
2018/12/02(日) 14:22:41.55ID:Bx+z5yQP
>>884
重いと言ってもC比だからな。
今時の超大富豪言語PythonやRubyとなら同程度でもおかしくはない。

Cygwinのshが重かったのはご存じの通りforkが原因だ。
気になるならVirtualBox等でlinux環境を構築してその上でテストしてみればいい。
0886デフォルトの名無しさん
垢版 |
2018/12/22(土) 02:10:55.36ID:V7w17XLB
gawk4にて配列の配列に存在する全要素数を
カウントする関数を作ったんですが、
もっと早いコードにならないでしょうか?
どなたかヒントをください。お願いします。

function count_array(arr, n, i) {
for (i in arr) {
if (isarray(arr[i])) count_array(arr[i], n);
else n[0]++;
}
return n[0];
}
0888デフォルトの名無しさん
垢版 |
2018/12/22(土) 20:12:58.98ID:VPYzPSxJ
886です。
ダメなんです。
BEGIN {
a[1] = 1;
a[2][1] = 21;
a[2][2] = 22;
a[3] = 3;
a[4][1][1] = 411;
a[4][2] = 42;
a[4][3][2][1] = 256;
for (i = 0; i < 9; i++) b[i] = i;
c["foo"]["corge"] = "grault";
c["foo"]["bar"] = "garply";
c["baz"]["corge"] = "waldo";
c["baz"]["quux"] = "fred";
print "length(a) = " length(a);
print "length(a) = " length(b);
print "length(a) = " length(c);
print "count_array(a) = " count_array(a);
print "count_array(b) = " count_array(b);
print "count_array(c) = " count_array(c);
}
length(a) = 4
length(b) = 9
length(c) = 2
count_array(a) = 7
count_array(b) = 9
count_array(c) = 4
再帰を使う以外に方法があれば、
と思い質問した次第です。
0889デフォルトの名無しさん
垢版 |
2018/12/22(土) 21:58:49.47ID:b6CiPLFa
要素を追加するときに
ノード毎に集計値が必要ならそれぞれのノード毎の集計値を保存しとけばいい
そうすれば集計しなおす必要ない

超速いハズ
集計しないからな
0890デフォルトの名無しさん
垢版 |
2018/12/22(土) 22:19:10.29ID:b6CiPLFa
こういった集計値がほしいのは分かる

aho(9)
┣aho1(5)
┃┣aho11(3)
┃┃┣aho111(1)
┃┃┗aho112(1)
┃┗aho12(1)
┗aho2(3)
  ┣aho21(1)
  ┗aho22(1)

lengthでは、きっとこんな感じでしかとれない

aho(2)
┣aho1(2)
┃┣aho11(2)
┃┃┣aho111(n/a)
┃┃┗aho112(n/a)
┃┗aho12(n/a)
┗aho2(2)
  ┣aho21(n/a)
  ┗aho22(n/a)
0891デフォルトの名無しさん
垢版 |
2018/12/22(土) 23:48:44.15ID:omdhpVTe
>>888
lengthは、配列aの要素に配列があると要素としての配列の
中の要素数まではカウントしない、やりたいのは要素としての配列に
含まれる要素もカウントしたい、ということか。

function count_array2(arr, cnt, i) {
n=0;
for (i in arr) {
if(isarray(arr[i])){
cnt+=length(arr[i]);
}
else n++;
}
return n;
}
だと

a[1] = 1;
a[2][1] = 21;
a[2][2] = 22;
a[3] = 3;
a[4][1][1] = 411;
a[4][2] = 42;
a[4][3][2][1] = 256;
a[4][3][3][2] = 257;

みたいなのでうまくいかない(1番目と2番目の添え字(?)が同じ)。
arr[i][j]...と続ければ(最初にlength(arr)で続ける深さを決めて)
いけるように思うが、だったら再帰するのが素直か。
0892デフォルトの名無しさん
垢版 |
2018/12/23(日) 00:54:43.50ID:quoNoaXg
886です。889さんこんな感じでしょうか?
BEGIN {
addnode(a, "1-1", "start");
addnode(a, "1-2", "done");
addnode(a, "1-3", "result");
addnode(a, "1-4", "print");
addnode(a, "2", "count");
addnode(a, "3-1-1", "return");
for (i in a[1]) print "a[1][" i "] = " a[1][i];
print "a[2] = " a[2];
print "a[3][1][1] = " a[3][1][1];
print "\n_ele_sum = " _ele_sum;
}
function addnode(arr, i, val, p) {
ct = split(i, list, "-");
switch (ct) {
case 1: arr[list[1]] = val; break;
case 2: arr[list[1]][list[2]] = val; break;
case 3: arr[list[1]][list[2]][list[3]] = val; break;
default:
}
_ele_sum++;
}
a[1][1] = start
a[1][2] = done
a[1][3] = result
a[1][4] = print
a[2] = count
a[3][1][1] = return
_ele_sum = 6
0893デフォルトの名無しさん
垢版 |
2018/12/23(日) 01:05:13.25ID:quoNoaXg
886です。
pとか関係ないパラメータ入れてしまってごめんなさい。
addnode(a, "1-5-1", "connot");
これができません。
a["5"]がスカラーだと言っています。
0894デフォルトの名無しさん
垢版 |
2018/12/23(日) 01:15:19.57ID:quoNoaXg
訂正a["1"]["5"]がスカラーの文脈だと言っています。でした
0895デフォルトの名無しさん
垢版 |
2018/12/23(日) 01:41:32.84ID:quoNoaXg
886です
for (i in a[1]) print "a[1][" i "] = " a[1][i];
でa[1][5][1]が引っかかっていたようです。
自爆でした。すみません。
0896デフォルトの名無しさん
垢版 |
2018/12/23(日) 02:59:04.54ID:quoNoaXg
886です。
親ノード毎?に保存する方法がまだわかりませんが、
明日以降考えます。
みなさん、ご協力ありがとうございました。
0897デフォルトの名無しさん
垢版 |
2018/12/23(日) 08:49:07.73ID:S8HMq/6c
gawk4でとにかく速いのが良いならcで拡張関数作るのが良いかと(反則?)

flatten_array_typed関数(4.1.4はflatten_array関数)でawk_flat_array_t構造体のメンバ変数countに要素数が入りますので
要素がAWK_ARRAYなら再帰するように処理すれば出来上がり

APIの使い方は
extension\rwarray.cとか
https://www.gnu.org/software/gawk/manual/html_node/Flattening-Arrays.html#Flattening-Arraysを参考に

gawkだけでやる場合、もし配列の要素数が10万とか100万あるのなら、関数の引数を出来るだけ減らして
関数内からグローバル変数を直接参照したほうが速くなると思います
0898デフォルトの名無しさん
垢版 |
2018/12/23(日) 11:20:10.63ID:qffc/3mK
もともと添え字がすべて文字列で保存する仕様というのはしってはいたが
多次元配列はaho[i,j]という形式にして工夫して使えということらしいな

awkで多次元配列なんか使ったことないから知らんかったわ

とういワケでにその形式で多次元配列をlengthでとると>>886で取得したい値になる
当然といえば当然
特定の次元の列だけのとりかたはよくわからん とれんのかコレ

 http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_12.html#SEC119
 Using Numbers to Subscript Arrays

  配列について重要なのは、配列の添え字は常に 文字列として扱われるということである。
  配列の添え字に数字を使った場合、それは添え字付けに使われる前に 文字列に変換される

 http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_12.html#SEC121
 Multi-dimensional Arrays

  多次元配列とは、配列要素の指定を複数の添字の並びによって行う配列である。例え ば二次元の配列は二つの添字を必要とする。
  一般的な(awkも含めた大多数の 言語では) 二次元配列の要素に対する参照は grid[x,y]このよ うに行う。 (gridは配列の名前)

  セパレータには組み込み変数SUBSEPに格納 されている値が使われる。
0900デフォルトの名無しさん
垢版 |
2018/12/23(日) 22:29:12.74ID:qffc/3mK
まず入力から多次元配列を読込む処理でも作ってみるか
できるのかがよく分からん

コレがすんなりできないとコレ自体が使えるシロモノにならなそうだしな

テストデータは作ってみた
https://ideone.com/Sir0IE

awkのこの多次元配列についてほかのとこで書いてあるの読んでみると
色々と面倒なことがおきるはのは分かった

特に問題がおきそうなのは一度配列やスカラーで要素を追加すると、
その配列やスカラーを変えて上書きする場合明示的にそれを削除しないと上書きして使えない

きっとなノードを削除するときはその要素゙から辿って一番深いとこから再帰的に削除しないと残骸が残る
cのメモリリークと同じことが起きると推定される

いまいちこの多次元配列に使い道があるのかどうかが分からない
0902デフォルトの名無しさん
垢版 |
2018/12/24(月) 01:01:19.83ID:ivcUrO89
https://ideone.com/PFBwQU

どうにかして動的に配列を構成できないか調べてみたが
やりかたが分からん

>>892の質問してるのが書いた方法で
一旦多次元配列を読む込むようにはしてみた

質問してるのが欲しいといってる要素の数は
結局入力の行数と同じになる
0903デフォルトの名無しさん
垢版 |
2018/12/24(月) 01:07:37.50ID:ivcUrO89
https://ideone.com/zTUFL2

switch分のcaseが1つ少なかったから追加しといた
0904デフォルトの名無しさん
垢版 |
2018/12/24(月) 09:11:50.63ID:PbNokzxn
>>900
> きっとなノードを削除するときはその要素゙から辿って一番深いとこから再帰的に削除しないと残骸が残る
delete a は a[1][2] や a[3][4][5] などの子配列含む配列a全体の使用メモリをまとめて "再利用" にまわす
一部の要素を残しておきたい事情が無ければ、delete a[1][2]; delete a[3][4][5]; ... のように子配列を個別に
deleteする必要は無い

たとえば下の(2)は多次元配列bが多次元配列aの使用済みメモリを再利用するので
終了間際のメモリ使用量は(1)(2)どちらも同じになるが、(2)の delete a を消すと倍程度に増える
(1) BEGIN{for(i=1; i<=1000000; i++){a[i%10][i]=i}}
(2) BEGIN{for(i=1; i<=1000000; i++){a[i%10][i]=i} delete a; for(i=1; i<=1000000; i++){b[i%10][i]=i}}

メモリ再利用の仕組みはThe GAWK Manualには書いていないけどAharon Robbinsが↓で回答している
https://groups.google.com/forum/#!topic/comp.lang.awk/CKwoes0_63U
0905デフォルトの名無しさん
垢版 |
2018/12/24(月) 15:58:51.02ID:ivcUrO89
なるほど
ありがとう

きっと再利用されるから
気にせず放置でいいのか
0906デフォルトの名無しさん
垢版 |
2018/12/24(月) 17:27:46.25ID:8PLVwc4u
>>902 886です。ありがとうございます。動的とはこんな感じでしょうか?
一度作って、削除するという変な仕様ですが。
BEGIN {
a[1] = "foo";
a[2][1] = "bar";
a[2][2] = "baz";
a[3] = "qux";
a[4][1][1] = "quux";
a[4][2] = "corge";

for (i = 1; i < 5; i++) {
meta_ar_init(b, i);
clone(b[i], a);
}
}
function meta_ar_init(ar, init_num) {
ar[init_num][1] = "";
delete ar[init_num][1];
}
function clone(lhs, rhs, i) {
for (i in rhs) {
if (isarray(rhs[i])) {
lhs[i][1] = "";
delete lhs[i][1];
clone(lhs[i], rhs[i]);
} else
lhs[i] = rhs[i];
}
}
0907デフォルトの名無しさん
垢版 |
2018/12/27(木) 20:01:48.39ID:pQqvXPza
よく分からんが
例えばそれで>>902の入力データなんかを読み込めたりするのか

>>903のswitchだと事前に何次元かわかってないと読み込めない

何次元になるか不明な入力データの場合
どうやれば格納できるかよくわからんんかった
0908デフォルトの名無しさん
垢版 |
2018/12/27(木) 22:46:53.38ID:X7jxTwwp
>>906の「一度作って、削除する」というのは
https://www.gnu.org/software/gawk/manual/gawk.html#Arrays-of-Arrays
ここの一番下のsplitがエラー吐く例の回避策で、配列の要素を最初から配列扱いすることはできないから
予め次階層にダミー要素をぶら下げておき、本命を格納し終えたらダミーは消すって意味かな

自分で書いたらこんなんなったけど、いちおう何次元でも格納できそう
https://ideone.com/83ykKF#stdin
0910デフォルトの名無しさん
垢版 |
2019/02/05(火) 18:58:36.44ID:9Z2hbdGL
60くらいの教授が40年くらい前にAWKでアセンブラ作ったとか言ってたんだけど
当時に既にあったということと当時から小規模なコンパイラなら作れるくらい高性能だったことに驚いた
0912デフォルトの名無しさん
垢版 |
2019/02/06(水) 10:31:17.59ID:+qagyc5o
aho
0913デフォルトの名無しさん
垢版 |
2019/02/06(水) 13:09:33.86ID:j4QdsmCl
asort、asortiがよくわからなかったので試した結果
# a
a[5] ="a5"
a[1] ="a1"
a[3] ="a8"
# asort(a,as)
as[1] ="a1"
as[2] ="a5"
as[3] ="a8"
# asorti(a,asi)
asi[1]=1
asi[2]=3
asi[3]=5

なんだそういうことだったのかとわかった
0914デフォルトの名無しさん
垢版 |
2019/02/06(水) 17:39:23.37ID:+3VpeZVh
>>910
思わず "assembler by awk" でググって The Amazing Awk Assembler by Henry Spencer を
ダウンロードしちゃったじゃないか。
0915デフォルトの名無しさん
垢版 |
2019/02/23(土) 17:41:13.06ID:Y0E0nwid
awkでファイルがあるかどうかの判別は、どのようにしたらよいのでしょうか?

具体的にはBEGINの中で

getline a < "/dev/stdin";
fn = a".txt"

と任意のファイル名を作った後、そのファイルがあるかどうかを確認したいんです。

もしファイルがすでにあったら処理は終了、無ければ以後の処理をそのファイルにリダイレクトする、という感じです。
0918デフォルトの名無しさん
垢版 |
2019/03/21(木) 08:10:09.34ID:pGDO/F2C
答えが出ないなんで?

#!/usr/bin/awk -f

BEGIN{
print game(10, 24);
}


function game(coin,depth, i,j){
if(memo[coin,depth]){
return memo[coin,depth];
}
if(coin == 0){
return 0;
}
if(depth == 0){
return 1;
}
win = game(coin + 1, depth - 1);
lose = game(coin - 1, depth - 1);
memo[coin,depth] = win + lose;
}
0919デフォルトの名無しさん
垢版 |
2019/03/21(木) 09:51:18.96ID:WMaCNtBE
最後の memo[coin,depth] = win + lose はそのまま関数の戻り値として
return しなければならないが、それを忘れている。

さらに、正しい答えが返らない原因が 2 点。
関数定義の引数名間違い: i,j → win,lose。
if(depth == 0) と if(coin == 0) の判定を行う順序が逆。
0920デフォルトの名無しさん
垢版 |
2019/03/21(木) 14:19:16.55ID:pGDO/F2C
>>919
ありがとうございます。
そっか。returnがいるんですね。
perlだと最後はreturn省略可能だけどawkは省略不可みたい。
あと、引数名も間違っていました。
正しい答え出ました!
0923デフォルトの名無しさん
垢版 |
2019/04/01(月) 17:01:28.78ID:nwflCE8J
>>921
awkの方がいいときもある

installしなくていい
タスクマネージャでみているとrubyよりメモリを食わない時もある
融通の利く配列が超便利

通信、Hash、sortなど使いまくる時はrubyのほうがいいけど
0924デフォルトの名無しさん
垢版 |
2019/04/01(月) 17:12:08.21ID:Tc5+6fel
いや、Perlだ。

理由
俺が慣れてるから。
0926デフォルトの名無しさん
垢版 |
2019/04/02(火) 04:44:16.86ID:3dIjgbOm
漏れは、Windows 10・WSL・Ubuntu 16.04 だけど、
sudo apt install ruby だけで、Ruby 2.3 が入った

2.4 以降の新しい書き方さえしなければ、動く

Perl, Python は、最初から入っているけど
レス数が900を超えています。1000を超えると表示できなくなるよ。

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