Perlについての質問箱 64箱目

レス数が1000を超えています。これ以上書き込みはできません。
2019/02/01(金) 09:44:37.18ID:1/Kr4Qjk
CGIについての質問は板違いです。WEBプログラミング板でどうぞ。
CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。
(WEBプログラミング板: https://medaka.5ch.net/php/

このスレでは(CGI以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。
スレ違いの質問にはスルーか、速やかな誘導をお願いします。
荒らしはスルー推奨。

"The duct tape of the Internet" こと、Perlについての質問箱です。
"There's more than one way to do it" ということで、
Perlの奥深さについて皆で語り合い、追求してまいりましょう。

www.perl.org/get.html
Download Latest Stable Source (5.28.1)

▼前スレ
Perlについての質問箱 61箱目
http://toro.5ch.net/test/read.cgi/tech/1381561905/
Perlについての質問箱 62箱目
http://toro.5ch.net/test/read.cgi/tech/1385039352/
Perlについての質問箱 63箱目
https://mevius.5ch.net/test/read.cgi/tech/1392820583/
2021/02/14(日) 01:36:58.65ID:u5RUQBwf
>>920
s/([¥x{10000}-¥x{1ffff}])/unpack(q{U},$1)/eg
かな?
ダメな気もするが。

つーか、さっきのURLにいろいろ書いてあるから、一度目を通して自分で試してみろ。
んで、うまくいったら、結果を貼るようにな。
2021/02/14(日) 07:32:21.90ID:kRUK3Bbl
$line =~ s/\x{1f306}/置/g;
これは成功する
$line =~ s/\x{1....}/置/g;
こんなことをやろうとしてた
$line =~ s/[\x{10000}-\x{1ffff}]/置/g;
これが正解だった
2021/02/14(日) 10:00:12.81ID:yrV2Bu9C
Perlの場合、マルチバイト文字で正規表現を正しく使うには、あらかじめEncode::decode()でデコードしておく必要があるので厄介。
2021/02/14(日) 11:18:28.10ID:u5RUQBwf
>>923
Perlに限らんやろ。
エンコーディングをまったく気にせず対応している処理系なんか存在しない。
925デフォルトの名無しさん
垢版 |
2021/03/03(水) 18:48:52.48ID:Q9ky3RP3
start:aaa1
end:bbb1
value:1.23
start:aaa2
end:bbb2
value:2.34

データとして上記のようなstart,end,value値が違うデータがだらっと繰り返ししてるファイルがあって
下記の正規表現で名前付きキャプチャを使って繰り返しマッチングし%+ハッシュを配列に格納したいのですが、こんな感じでやるとそれぞれのデータが順に入ってしまいます。
どう書けばマッチングした各ハッシュを配列に格納出来るのでしょうか?
$re=qr|start:(?<start>\S+).*?end(?<end>\S+).*?value:(?<value>\S+)$|sm;
my @data = m|$re|g =~ $txt;
2021/03/03(水) 20:20:14.74ID:DgitZS9x
正規表現を使うところではない気がするな。w
ちょっとおちついて、行単位で処理していけよ。
927デフォルトの名無しさん
垢版 |
2021/03/03(水) 23:36:11.18ID:Q9ky3RP3
>>926
そういうもんなんですか?
pythonだとre.finditerでイタレータ毎に取れるので似たような感じにperlでもどうにか出来るんだろうと思ったのですが無理そうなら諦めます
2021/03/04(木) 00:03:04.76ID:ls8aTj6l
Ruby なら、

line_num = 0 # 行番号

# 行末の改行を削除して、1行ずつ処理する
results = File.foreach( "test154_data.txt", chomp: true ).with_object( [ ] ) do |line, accm|

line_num += 1
# 3行毎に、ハッシュを作って、蓄積変数に追加する
accm.push Hash.new if line_num % 3 == 1

ary = line.split( ':', 2 ) # 左からコロンで、2つに分割する
hash = accm.last # 最後の要素
hash[ ary[ 0 ] ] = ary[ 1 ]

end

p results

出力
[{"start"=>"aaa1", "end"=>"bbb1", "value"=>"1.23"},
{"start"=>"aaa2", "end"=>"bbb2", "value"=>"2.34"}]
2021/03/04(木) 00:11:02.54ID:Pkas/NOZ
>>927
可不可の話なら、while (m/start..end/g) {...}みたいにしたらきっとできる。

しかし、オレならやらん。
Pythonは詳しくないが、たぶんそれでもやらんやろなあ。

正規表現の使いどころとしては非効率的だし、エラー対応が非現実的だし。
また、対象はファイルの内容だそうだが、ReDoSは知ってるか?
2021/03/04(木) 00:24:13.90ID:u/riWi2o
なんで急にRubyが出てくるんだよ(呆れ
2021/03/04(木) 00:42:19.66ID:2AXWpxTy
perlリスペクト公言言語だから敬意を評してるんじゃないかな、大目に見てあげよう
2021/03/04(木) 09:09:52.94ID:8OZ033Zi
元がファイルだからなあ
1行ずつ分かれてるものを合体させてまた分離する、というのが無意味に見える

正規表現は柔軟性なので、使わなくていいくらいかっちりしてるものには
使わない方が安全側に倒れる
元ファイルが手書きで、無駄な改行やコメントが入ってるなら正規表現
933デフォルトの名無しさん
垢版 |
2021/03/07(日) 10:07:03.25ID:Anqe+9Rf
forkがハングする。

見えてる範囲だと、memoryの使用量が関係してかもしれないです。
firefoxを使って1G程度メモリを食わせてからスクリプト走らせると、forkが返ってこなくなる。
この時のメモリ使用量は他も併せて25%程度。閉じてから再度走らせるとちゃんと動く。
エラー値返してくれたら助かるのだけど、ハングなんで困ってます。
アドバイスいただけるとたすかります。

Strawberry perl 64bit 5.32.1
Windows10Pro 64bit version 2004
Corei3-4370, Memory 12G
2021/03/07(日) 10:45:56.10ID:Q92Mc+WL
安定して動かないならバグっている

だいたい動くけど、ごく稀に動作がおかしい、ということがforkはある
forkがコケても動くような仕組みにすればok
2021/03/07(日) 10:50:58.30ID:x9JK9zFw
そもそもWindows APIはfork()をサポートしてない。
2021/03/07(日) 11:48:43.53ID:Anqe+9Rf
>>934 ありがとう。
メモリ使用量が低いと成功。
firefoxでもタブ1枚ぐらいなら成功。
firefoxでタブ(yahoo.com)10枚開くと、確実にハング。

ラクダ本にも、失敗(戻り値undef)の対処法が書いてありますね。
WindowsOSがらみなので、イロイロありそうなのは察します。
でも、forkを呼び出したらハングして帰ってこないからなぁ。
コケるというよりは、forkを呼び出さない:
  if( $can_fork ) {fork;}
ってな書き方が必要になってしまう。
2021/03/07(日) 11:53:44.14ID:Anqe+9Rf
追記:
perlスクリプトとfirefoxは関係ありません。
単に、デスクトップで調べものしながら、コマンドプロンプトでperlインタプリタ
を起動して作業しているだけです。連投失礼しました。
938デフォルトの名無しさん
垢版 |
2021/03/07(日) 12:10:59.62ID:3xq9+JKJ
ActivePerl の Windows 版では fork() がエミュレーションされているらしい。

実際に呼び出してみるとスレッドがひとつ増える。
中ではおおかた CreateThread() でもしてるんだろう。
2021/03/07(日) 12:24:40.47ID:xy+MS7Fg
windowsで安定動作させたいならforkを使わずに自分で別スレッドか別プロセス立てるのが吉
2021/03/07(日) 14:22:59.45ID:Anqe+9Rf
>>938
perldocによると、ActiveStateとMSが頑張ったらしいよ。
エミュあつかいとのことです。

>>939 ありがとう。
スレッドでするわ・・・さすがにハングはだめだわ(^^;
2021/03/07(日) 14:48:48.37ID:Q92Mc+WL
forkとか再帰呼び出しとか、魔術的で楽しいけど、大抵罠にはまる
2021/03/07(日) 17:38:53.17ID:quYd9iFF
再帰はええやろ。
forkはもともとUNIX用で、Windowsとは相性が激悪なだけやから、しゃあない。
2021/03/07(日) 17:49:12.06ID:Q92Mc+WL
階層ディレクトリを辿る、みたいなとこに再帰を使うと止まらなくなったりする
絶対止まると保証されてるとこにしか使えなくて、そういうのは別に再帰でなくてもやれる

隅々までどうなってるか判らないものに再帰は威力を発揮するけど、
そういうのは往々にして停止性が保証されない
2021/03/07(日) 18:11:41.00ID:eIiM+J9a
それはあんたが無能だから
2021/03/07(日) 18:18:17.98ID:x9JK9zFw
Perlと関係ない話はよそでどうぞ
2021/03/07(日) 23:39:46.89ID:quYd9iFF
>>943
再帰終了をちゃんとできないヤツは、ループ終了もできないやろ。w

ディレクトリうんぬんに限って言えば、ファイルシステムへの知識が足りないとかか。
リンク系の。
2021/03/07(日) 23:53:02.15ID:Q92Mc+WL
軽く考えてるけど、プログラムの停止性ってもっそい奥が深い
ゲーデルの不完全性定理と密接に絡んでる
2021/03/08(月) 00:03:00.68ID:RDgJTpCR
tarのhオプションってよくできているよな
無限ループに陥りやすいが
2021/03/08(月) 00:23:56.56ID:tQicr2bh
再帰処理は考えてるの楽しいよな
実装するかとなると状況次第
2021/03/08(月) 01:47:35.66ID:6lKYXbK2
>>947
バグが存在しない証明は超難しいから、ふつうやらない。
かわりに、テストを必要なだけする。
それだけのこと。

原理とやらは学者に任せておけばいい。
2021/03/08(月) 10:04:20.07ID:XzCJxGl3
ggl先生に "perl dir tree" で検索かけたら自作ページが多いね。
安心安全鉄板ライブラリとかってあるかな?
素人考えでなんだけど・・・OS別、FS別なんてあるんかの。
2021/03/08(月) 10:17:22.69ID:SORPad+v
親にリンクしていてループするのが困るので、
全部の子に対してカウンタを持たせる、くらいしか回避方法が無いんだよな
それだと再帰でやってるうまみが無くなってしまう
2021/03/08(月) 12:03:45.46ID:JySUELLY
素直にFile::Find使っとけ
2021/03/08(月) 12:34:19.76ID:SORPad+v
dir /s の結果を使うのが一番楽
2021/03/08(月) 16:27:27.25ID:3P7OMB5d
File::Findは処理速度が遅いのが難
2021/03/08(月) 17:21:12.95ID:6lKYXbK2
>>952
リンクを不用意にたどるな。
既存コマンドでもオプションにしがちだし、ディレクトリ構成によっては死ぬくらいだから、しゃあない。
2021/03/08(月) 17:24:47.95ID:6lKYXbK2
>>955
何と比べて?
no_chdirを指定したりしたらマシになったりしない?
2021/03/08(月) 17:40:53.14ID:SORPad+v
ディレクトリならどこかにある実体のコピーだろうから、リンクなんか無しで済むけど、
より一般化したリスト構造だったら辿らない訳にいかない
だから、事前にループしていないことを確認してから処理することになって、
そのテストがループにはまる
959デフォルトの名無しさん
垢版 |
2021/03/08(月) 20:06:16.14ID:3P7OMB5d
>>957
試してみたが、no_chdirは関係ない。
File::Findは、dir /S /B コマンドのパイプ読み取りに比べて、3倍も時間がかかる。
File::Findは遅いだけでなくコールバックでユーザー変数を扱えない欠点があるから、私はFile::Findを使わない。
960デフォルトの名無しさん
垢版 |
2021/03/08(月) 21:30:38.88ID:3P7OMB5d
File::FindはUnix系OSで使う場合は find コマンドのパイプ読み取りと同等か少し速い。
File::Findが明確に遅いのはWindows向けにビルドされたPerlの場合のみ。
2021/03/08(月) 22:05:40.64ID:6lKYXbK2
>>960
WindowsのどのPerl?
ひょっとしてCygwin版?
ActivePerlやMSYS2版ならマシだったり?
962デフォルトの名無しさん
垢版 |
2021/03/08(月) 22:39:10.09ID:3P7OMB5d
>>961
残念ながらネイティブに最適化されているはずのActivePerl や Strawberry Perl でFile::Findが遅い。
原因は知らないけどWin32APIの使い方が良くないからだと思う。
963532
垢版 |
2021/03/09(火) 00:11:34.07ID:jxvXMO9/
$^WIN32_SLOPPY_STAT じゃね?

File::FindはWindowsだと、SJISで全角「構」などの2バイト目が\(0x5c)のフォルダに遭遇すると
無限loopしたり誤動作するから、結局Wndowsでフォルダ階層を再帰的にたどるには
utf8化したperl sourceで自分でopendir, readdirして、encode, decodeせにゃならん。
964532
垢版 |
2021/03/09(火) 00:15:08.81ID:jxvXMO9/
別件だがWindowsではSJISで全角「構」などの2バイト目が\(0x5c)のフォルダには
perlからlstatやutimeが出来ないみたいで難儀した。
Linuxのutf8のファイルシステムと違ってWindowsのSJISファイルシステムは面倒
2021/03/09(火) 01:17:12.50ID:B0uPByTP
>>962
そうやったか。。。

>>964
NTFSファイルシステム自体はUTF-16やぞ?
MicrosoftがようやくいよいよコマンドプロンプトとかNotepadとかのUnicode対応を考えはじめてるし、いずれWindows版も対応するんちゃうか。
いっそツッコんだら?
966928
垢版 |
2021/03/09(火) 05:19:08.22ID:NUN2sKP0
>>925
Ruby で、元のファイルを、CSV へ変換してみた。
データ中に、ダブルクォーテーション・カンマを入れても、正常に動く

require 'csv'

line_number = 0 # 行番号

# 行末の改行を削除して、1行ずつ処理する。蓄積変数は2次元配列
results = File.foreach( "input.txt", chomp: true ).with_object( [ ] ) do |line, accm|
line_number += 1
accm.push [ ] if line_number % 3 == 1 # 3行毎に、空配列を追加する

ary = line.split( ':', 2 ) # 左からコロンで、2つに分割する
last = accm.last # 最後の要素 (配列)
last.push( ary[ 1 ] ) # コロンの右側を、配列に追加する
end

results.unshift %w(start end value) # 先頭に、ヘッダー行を追加する
# p results

csv_str = results.map( &:to_csv ).join # 2次元配列を、CSV 文字列に変換する
print csv_str

出力
start,end,value
a_1,"b""1",1
"a,2",b_2,2.34
967デフォルトの名無しさん
垢版 |
2021/03/09(火) 08:00:45.91ID:4CK4kuWA
コマンドプロントはとっくにUTF-16対応している。出力フォントが表示に対応していないだけ。
コマンドプロントにはもう機能追加されないから Windows Terminalに乗り換えたほうがいい。
968デフォルトの名無しさん
垢版 |
2021/03/09(火) 08:27:17.16ID:4CK4kuWA
コマンドプロントは今でもすでに非システムコード文字(アラビア文字やハングルなど)をコマンドに引数渡しできる。
受け取る側のアプリがUTF-16形式で起動時の引数を取らなかったり、batファイルが非システムコード文字に対応していないだけ。
コマンドプロントの努力だけではどうしようもない。

なお、Windows向けビルドされたJavaやPerlは非システムコード文字を引数で受け取れない制約がある。
プログラム側で自力でbase64エンコード対応するなどして回避するしかない。

一方、Windows向けビルドされたPythonは非システムコード文字を引数で受け取ることができる。
Pythonのプラグインを作ったことある人なら分かると思うが、Pythonはインターフェース間の文字列のやりとりにUTF-16を使っている。
2021/03/09(火) 08:33:53.42ID:HJK4uNxM
UTF-16も嬉しくない
970532
垢版 |
2021/03/09(火) 08:45:38.83ID:UTQZC5u1
NTFSってUTF-16だったのか、
しかしperlのreaddirはcp932で返してきているような気がs…
2021/03/09(火) 09:28:02.71ID:HJK4uNxM
NTFSはUCS-2で、windowsがUTF-16
それをわざわざcp932に変換して寄越す
2021/03/09(火) 10:42:13.66ID:4CK4kuWA
NTFSもUTF-16だと思うよ。
2021/03/09(火) 10:44:51.95ID:SbXzcieK
>>968
> コマンドプロントの努力だけではどうしようもない。

そらそうや。
ついにcp932から離れようとする世の方向性を受けて、Perlも変わるんじゃねえの、という話。
Perl7とかでそういう話は出てないんかな?
知らんけど。

> なお、Windows向けビルドされたJavaやPerlは非システムコード文字を引数で受け取れない制約がある。

制約つーか、むしろ互換維持とかただ昔のままほったらかしとかやろ。w
2021/03/09(火) 10:56:11.55ID:SbXzcieK
>>971
そのおかげで、20年以上昔からふつうにWindowsで使えてきたわけだからしゃあない。
むしろありがたかった話。
2021/03/09(火) 12:55:12.46ID:NUN2sKP0
Windows 10 Home でも、Docker が出来るようになった。
ただし、Windowsの連続更新に、3時間も掛かったけど

WSL2, Ubuntu でも使えば?
漏れは、Ruby on Rails をやってる

Linux側には、日本人が作った、バージョンマネージャーのanyenv で、
rbenv, nodenv を使って、ruby 2.6.6, node 12.16.2 も入れた

Dockerでも良いし。
ただし、メモリ8GB じゃキツイ。16GB は欲しい
976デフォルトの名無しさん
垢版 |
2021/03/09(火) 20:18:30.71ID:BijZjsz/
正規表現のパターンの中に変数を書くとおかしくなりますが、どうしたらいいでしょうか。

やりたいこと:「hoge」の後ろがカンマか行末の場合を抽出したい

$pat = "hoge[,\$\]";
if( $str =~ m/$pat/ ){...}

こう書くと $pat が「hoge[,$]」になることはデバッガで確認できたのですが、思った通りのマッチになりません。マッチングの部分に $pat ではなく定数で「hoge[,$]」と書けばマッチングします。

どう書いたらいいでしょうか?
2021/03/09(火) 20:28:25.57ID:HJK4uNxM
なんで ] だけエスケープしてるの?
2021/03/09(火) 20:34:49.51ID:nUvu3sQ4
そういうときの為のqrですよ
2021/03/09(火) 20:36:21.19ID:XI91xcQL
[]内は文字セットだからその$は行末マッチじゃないし
980976
垢版 |
2021/03/09(火) 22:41:12.95ID:BijZjsz/
色々やって混乱して間違った事を書いていました。
やりたいことは >>976 の通り。
>>979を見てそれならばと「$pat = "hoge,{0,1}\$"」と書いたら目的を達成できました。

お騒がせしました。
2021/03/09(火) 22:43:46.86ID:HJK4uNxM
{0,1}って?と等価だよね
2021/03/09(火) 23:03:58.63ID:B0uPByTP
>>980
hoge,xxxx
にはマッチしないが、ええんか?
>>976の目的と違うで。
2021/03/10(水) 02:28:31.13ID:ixLG+AYE
hoge(,|$)

やりたいのはコレじゃない?
2021/03/10(水) 06:16:01.51ID:S+G6vYN6
>>980
近いといえば近いが、そういう書き方をしたいなら「, で始まる文字列」じゃないか。
hoge(,.*)?$

あと、Perl には \z もあるよ。
985976
垢版 |
2021/03/11(木) 11:15:21.72ID:VAAe2gi6
みなさん、こんなアホに付き合ってもらってありがとうございます。
疲れてたのかな、俺。

まだ試してませんが、教えていただいたやり方でチャレンジしてみます。
986532
垢版 |
2021/03/11(木) 11:39:56.33ID:AlcqB+X5
$pat = 'hoge(?:,.*)?$';
print "1\n" if 'hoge,dsad' =~ $pat;
print "2\n" if 'hoge' =~ $pat;
print "3\n" if 'hage' =~ $pat;

はどうよ

実行例
~ $ perl 64_976_hoge_pat.pl
1
2
2021/03/11(木) 14:27:02.78ID:IdZJgmDv
もしかして
¥bhoge¥b
がよかったんじゃないの?
2021/03/11(木) 14:37:57.64ID:l5V9NIZG
splitをうまく使うと解決したかも
2021/03/20(土) 13:47:35.09ID:UD6ZNZG9
2021/03/20(土) 13:51:21.40ID:UD6ZNZG9
Python勉強中

print('梅')
exit()
2021/03/20(土) 17:31:10.22ID:ql2G31oz
【モダン推奨】Perlについての質問箱 50箱目
https://mevius.5ch.net/test/read.cgi/tech/1327110999/
2021/03/21(日) 17:34:20.99ID:2t2VtxHB
2021/03/21(日) 17:36:32.63ID:dkvLNxnd
2021/03/21(日) 17:39:12.82ID:2t2VtxHB
うぜ
2021/03/21(日) 21:54:16.28ID:6DoINzzO
2年で消化 人気スレじゃねーか
2021/03/22(月) 01:23:08.94ID:rCEIiEgY
うめ
2021/03/22(月) 23:39:18.97ID:rCEIiEgY
2021/03/22(月) 23:39:30.86ID:rCEIiEgY
2021/03/22(月) 23:40:13.68ID:rCEIiEgY
質問いいですか?
2021/03/22(月) 23:41:34.32ID:rCEIiEgY
おしまい
10011001
垢版 |
Over 1000Thread
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 780日 13時間 56分 57秒
レス数が1000を超えています。これ以上書き込みはできません。
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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