Regular Expression(正規表現) Part14 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
Regular Expressionスレです。
質問する場合は必ず実装言語や処理系ソフトウェア名を示してください。
前スレ
Regular Expression(正規表現) Part13
http://echo.2ch.net/test/read.cgi/tech/1415149975/
次スレは>>980宜しく
天ぷら等2以降 >>491
https://ronsavage.github.io/SQL/sql-2003-2.bnf.html
こいつのcharacter string literalとか読め
ちゃんと規格化されてるんだからさ
その上で正規表現で書くのは難しいって話 試しに Perl でやってみた。最も楽観的な想定ならこのくらいまでは手抜きできる。
use strict;
my $comment = qr/(?:--.*?\n)/ ;
my $literal_ch = qr/(?:\'\'|[^\'])/ ;
my $ch_str_literal = qr/(?:\'(?>$literal_ch*)\')/ ;
my $other_ch = qr/[^\';]/ ;
my $some_str = qr/(?:$comment|$ch_str_literal|$other_ch)/ ;
my $statement = qr/(?:$some_str*;)/ ;
my $text = '';
while (<>){ $text .= $_; while ( $text =~ s/^$statement// ){ print("Found:$&\n") }}
文字列リテラルの中の文字の記法に特に対処すべき拡張があるなら $literal_ch に加えれば良い。
" は識別子を書くためのものだが '、;、-- のどれかが入る可能性があるなら $other_ch と $some_str に加えればいいだろう。
多分、問題はそこではない。この例では行単位の入力だから面倒な問題を回避できているが、そうでない場合の問題だ。
たとえばコメントの始まりの - までしか読まれていないという場合。もっと読まなければコメントかどうか判断できない。
あるいは文字列リテラルの中で ' が現れた場合。それは文字列リテラルの終わりなのか、それともリテラルの ' を表す '' の 1 文字目なのか。
こういう処理を自分で書くのは難しくはなくても面倒だし、処理速度も遅い。だから結局 flex を使ったりする。 仕様通りのParser とか、構文解析ツールが必要
それらを使って出力された、抽象構文木を使うのがよい ★タイトル
★★タイトル
上のものにマッチさせたいのですが、
^★.*$
としてしまうと、下まで含まれるのですが、どうしたらいいでしょうか ↑解答どうも
できなかったです
ちなみにmeryというテキストエディタの正規表現です
何の言語かはわかりませんが https://regex101.com/r/YyXfr8/1
鬼雲みたいだし動くと思うんだけど, 先頭とか末尾に余計なスペース入ってない? ↑ありがとうございます。行けました。
.*の前に否定を入れればいいんですね 正規表現をちゃんと論理的に導きたいと思って参考になる本を
買ったら必要な予備知識に群とか環が出てきて即諦めた
正規表現周りの開発をしてる人達はすごい人達なんだなぁ
すごさを直で実感出来た 用語に慣れてないだけだろ
やってることは大したことじゃない まぁ膨大な時間と労力をかければ自分にも分かるんだろうけど
現実的じゃないんだよなぁ(人の何倍も時間かかるだろうし)
これからは正規表現技術者の努力に感謝しながら正規表現を
使おうと思います(^^)> JavaScriptによる正規表現チェッカー
くっそ長いので短縮
https://goo. gl/CE3aZ8
https://fatiherikli.github.io/fil/#eyJwYXRoIjoiSmF2YVNjcmlwdFRlc3QxLmpzIiwic291cmNlIjoiLyog5q2j6KaP6KG
o54++44Oe44OD44OB44OG44K544OIICovXG5cbi8vIOato+imj+ihqOePvlxudmFyIHJlID0gbmV3IFJlZ0V4cCgv
XFxkKy9nKTtcblxuLy8g44OG44Kt44K544OIXG52YXIgdGV4dCA9IChmdW5jdGlvbiAoKSB7LypcbmFhYVxuYmIx
MmJcbmM1NjdjYzg5XG4qL30pLnRvU3RyaW5nKCkuc3BsaXQoL1xcbi8pLnNsaWNlKDEsLTEpO1xuXG5jb25zb2x
lLmxvZyhcIlJlZ0V4cDpcIiwgcmUudG9TdHJpbmcoKSlcbmNvbnNvbGUubG9nKFwiVGV4dDpcIiwgdGV4dCk7XG5c
bnRleHQuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgY29uc29sZS5sb2coXCJsaW5lOlwiLCBsaW5lKTtcbiA
gICB2YXIgcmVzdWx0ID0gbGluZS5tYXRjaChyZSk7XG4gICAgaWYocmVzdWx0KVxuICAgICAgICBjb25zb2xlLmxv
ZyhcInJlc3VsdDpcIiwgcmVzdWx0KTtcbiAgICBlbHNlXG4gICAgICAgIGNvbnNvbGUubG9nKFwicmVzdWx0OlwiLCBcIm51bGxcIik7XG59KVxuIn0 ちょっと修正
https://goo. gl/M2Fn68 Linuxに触れるまで正規表現に方言があるなんて知らなかった
基本正規表現だの拡張正規表現だの
vimの置換で悩んでたら原因がエスケープの有無が原因とかもうね
ある程度は使えるが先読みとか後読みとか僅かでも深入りすると余計に混乱する 小さい世界で囲い込まれてれば楽だよな
ただし何かの拍子ではみ出した時に世界の広さを知って己の無力さを痛感する
よくあるパターン 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
QBPEH HTMLの解析を正規表現でやりたいのですが
<a href="xxxxx"><img src="yyyyy" /></a>
という風に、<a> で括られた img の src だけを抽出したいんですけど
どうしたらいいのでしょう。
<a> で括られてない
<img src="yyyyy" />
は除外したいのです。 あ、すみません
<a href="xxxxx"><img src="yyyyy" /></a>
<a href="xxxxx">あああ<img src="yyyyy" /></a>
<a href="xxxxx"><img src="yyyyy" />いいい</a>
<a href="xxxxx">あああ<img src="yyyyy" />いいい</a>
<a href="xxxxx"><img src="yyyyy" /><div>あああ<div></a>
みたいに、<a> の中は <img> 以外のゴミも入ってきます。
※ゴミは無視したい >>512
^<a\b.+<img src="([^"]+)".+</a>$
↓
$1 >>513
<a href=""></a><img src="1.jpg"><a href=""></a> 頑張ってみてもこの程度が限界
https://regex101.com/r/VYrYNO/1
で, >>511がHTMLの解析を正規表現だけでやる理由は何だ?
Pythonのhtml.parser, RubyのNokogiri, PHPならGoutter, それ以外の言語でも間違いなくHTMLパーサは誰かしら作ってる
そんな中で何故正規表現だけで?ぶっちゃけこういう用途には向いてない, というかHTMLの構文規則は正規言語を超えるんだけど, 分かってる? パーサかましてXPathで必要な情報だけ抜くのが基本だしな
どうしても使えないっていう理由があるなら仕方ないけど 鬼雲限定
<a (?~</a>)<img src="([^"]+)"[^>]*>(?~<a )</a> ■変更前
004a34
A521n2
785b66
■変更後
0049934
99521992
7859966
----------------------
数値以外を99に置換したいです
お願いします 木構造のものは、正規表現じゃ無理
1< 2< abc 3> 4>
2<からの最短マッチで、対応する3>を取れるけど、
1<からの最短マッチで、対応する4>を取れない。
3>にマッチしてしまうから
1< 2< 3< abc 4> 5> 6>
これでも、2<と5>をマッチさせられない。
最長・最短マッチでも、マッチしない
CSS セレクターを使う、jQuery, RubyのNokogiri などを使え。
これらの使い方は、ほぼ同じ >>518
数値以外と簡単に言うが改行文字や空白等の扱いはどうするんだ
変換対象文字をちゃんと明示しないと
/[^0-9]/99/g
こんなもんが欲しいわけではあるまい
とりあえずASCII印字可能文字に限るなら
/[\x21-\x2F\x40-\x7E]/99/g
だが当然マルチバイト文字は対象外 >>519
再帰を使えば、対応する括弧のネスト対応ぐらいならできるらしいよ(鬼雲、PCRE)
<([^<>]++|(?R))*>
# [^<>]++は(?>[^<>]+)としてもよい(どっちもバックトラックしないと思う)
# (?R)は、(?0)とも書ける
# (<([^<>]++|(?1))*>)
\g<-n>を使ってもできる(鬼雲だけ?)
(<(?:\g<-1>|[^<>])*>)
# \g<-1>は(?-1)とも書ける
# ここでは\g<-1>を先に書いたが上と同じく後ろに書いても同じ https://regex101.com/r/VYrYNO/1
なぁこれメンテしたいか?というか出来るか?なぁ?
(?i:<a(?:\s+[a-z][a-z0-9]*(?:=(?:"[^"]*"|'[^']+'))?)*>)
((?:
(?i:<img(?:\s+(?:src="([^"]+)"|[a-z][a-z0-9]*(?:=(?:"[^"]*"|'[^']+'))?))*(?:\s*\/)?>)
|(?i:<([a-z][a-z0-9]*)(?:\s+[a-z][a-z0-9]*(?:=(?:"[^"]*"|'[^']+'))?)*>(?1)<\/\3>)
|(?i:<[a-z][a-z0-9]*(?:\s+[a-z][a-z0-9]*(?:=(?:"[^"]*"|'[^']+'))?)*\s*\/>|.*?))*)
(?i:<\/a>) 文字列の中から数字13桁(それ未満でも超えてもNG)を抽出するにはどうしたらいいでしょう
JANコードらしきを抜き取りたいのです。
候補を抽出してから後でチェックデジット計算しますので
数字13桁のみで大丈夫です。 \b[0-9]{13}\b
とか
(?<![0-9])[0-9]{13}(?![0-9])
とか
携帯だから試してない 先頭と末尾も考慮すると
https://regex101.com/r/xT760t/2
(?:(?<=[^0-9])|^)[0-9]{13}(?:(?=[^0-9])|$)
ただかなりバックトラックするから性能は悪い
どうせチェックディジット確認するなら13桁以上で全抽出して桁数チェック追加した方がマシに見える
https://regex101.com/r/xT760t/4
[0-9]{13,} 結構、難しい
A <13桁の数字> B
A の部分が、文字列の先頭か、数字以外で、
B の部分が、文字列の末尾か、数字以外 文字列操作可能なら両端に数字以外の文字を付加して
[^0-9][0-9]{13}[^0-9]
かな >>531
先読み後読みは先頭や末尾にも一致するからそういうのは無駄
>>530の二つ目で完成している >>534
せやな, 否定前後読みならそのままでよかったわ(肯定で試しちゃった)
ただどのみちバックトラック多くて無駄だから正規表現だけでやるのでなければ13桁以上でマッチングして桁数判定入れるべきだと思う 13桁を超えていても候補として受け取っておいて
チェックデジットの計算の手前で落とします。
どうもありがとうございました。 文字列の先頭の文字以外を*に変換する
というのはどう書けばいいでしょうか? こういうこと?
$perl -pe 's/(?!^)./*/g'
alpha
a****
beta
b***
gamma
g****
$
良い方法かどうかはわからないが。 perl -pe 's/(?<!^)./*/g'
とすべきだったかな。 1 2 3 の3つの文字を、順番不同で、必ず各々、1つ以上含む
a23b1 → 真
1a2 → 偽
これは順番の組み合わせだから、正規表現で出来ますか? >>542
先読みが使えれば
^(?=.*1)(?=.*2)(?=.*3) サクラエディタで
<>で囲まれていないaaaをあああにしたいです
<aaab>aaa<caaadaaa>baaadeaaa<ccc>baaad<baaa>aaabaaadaaa<ee>
↓
<aaab>あああ<caaadaaa>bあああdeあああ<ccc>bあああd<baaa>あああbあああdあああ<ee>
>([^<>a]*?)(aaa)([^<>a]*?)<
>$1あああ$2<
だと「>aaa<」や「>baaad<」は置換できるけど「>baaadeaaa<」や「>aaabaaadaaa<」が置換できずに残る
そこで
>([^<>a]*?)(aaa)([^<>a]*?)(aaa)([^<>a]*?)<
>$1あああ$2あああ$3<
と変換するわけですが当然「>aaabaaadaaa<」が残り…
<>に囲まれていないaaaが沢山あるので変換しきれません
何とかならないでしょうか []内のa取っ払って
ぜんぶ変換できるまで何回もやったら?
(>[^<]*?)aaa([^>]*?<) aaa(?=[^>]*<)
前後に必ずタグがあるならこれなら一回 >>545>>546
できた!できました!
ありがとうございます ●
パターン1, (\d+)月(\d+)日
パターン2, (\d+)月(\d+)数字以外(\d+)日
これを一回で取得したい
●対象データ
7月1日
7月2〜4日
7月6から10日
7月12・13日
●希望する結果
7,1
7,2,4
7,6,10
7,12,13
お願いします 取得って何だよ変数に入ればいいのか置換結果として取得したいのか >>548
ほんまにそれが希望する結果?
数字とりだしてるだけなんだけど。 数字取り出して変数に入れるだけなら /(\d+)月(\d+)(?:\D+(\d+))?日/gu で仕舞いだが 変数にキャプチャしたいのか置換で取り出したいのかくらい書こうな C#で正規表現を使ってHTML内から文字コードをとってきたいのですが
以下の場合だと"UTF"としか取得できません。
"UTF-8"と取得する場合どうすればいいでしょうか?
<[^>]*\bcharset\s*=\s*[""']?(?<charset>\w+)\b
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"> >>556
HTMLは扱いが難しいからパーサ使った方がいい
どうしても正規表現だというなら,
1. とりあえず的な修正
https://regex101.com/r/sIUmzD/2
/<[^>]*\bcharset\s*=\s*(?:([^\s"'=><`]+)|'([^']*)'|"([^"]*)")\b/$1$2$3/i
2. もう少し気合の入れた修正
https://regex101.com/r/sIUmzD/1
|<meta
(?:\s+[^\s"'>/=]+(?:\s*=\s*(?:[^\s"'=><`]+|'[^']*'|"[^"]*"))?)*
(?:\s+charset(?:\s*=\s*(?:([^\s"'=><`]+)|'([^']*)'|"([^"]*)"))?)
(?:\s+[^\s"'>/=]+(?:\s*=\s*(?:[^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>|$1$2$3|i
ぐらいか
でもこれ後で読むのしんどいでしょ 2.の方を若干修正, charsetには値が必要ですわ
https://regex101.com/r/sIUmzD/3
|<meta
(?:\s+[^\s"'>/=]+(?:\s*=\s*(?:[^\s"'=><`]+|'[^']*'|"[^"]*"))?)*
(?:\s+charset\s*=\s*(?:([^\s"'=><`]+)|'([^']*)'|"([^"]*)"))
(?:\s+[^\s"'>/=]+(?:\s*=\s*(?:[^\s"'=><`]+|'[^']*'|"[^"]*"))?)*\s*/?>|$1$2$3|i >>557
ありがとうございます!
当方がやりたかったことは、HTMLをテキストデータとして大量に取得して、その中から特定のワードでの絞り込みです。
正しい文字コードでHTMLを落としてからパースしようと思ったのですが、確かにパーサでやる手もありそうですね
正規表現は今まで避けてきたので、読むのがシンドイっていうかチンプンカンプンですが
求めていた動作です。とても助かりました。
使わせてももらいます。ありがとうございました。 HTML のように、要素に親子関係があるもの・構造化されたものは、正規表現じゃ無理
<1><x></x><y></y></1>
開き・閉じタグで、前から一致させると、
<1></x> が対応してしまう
ネストも無限にできるから、対応させるのは無理。
パーサを使うべき >>561
一部の環境では括弧等のネスト構造を取り扱いをサポートした正規表現があるよ
PCRE(Perl 5.10以降)やruby(鬼雲)、Python,PHPなどでも
C#の.NET Framework環境でもあったんじゃないかな .*
何にでもマッチさせることができる最強で万能な正規表現 >>561
> HTML のように、要素に親子関係があるもの・構造化されたものは、正規表現じゃ無理
そういうこともできるように拡張した正規表現があればいいのに
さらに階層、treeも可 なんか知識が数年前で止まっちゃってる人がちらほらいるな
正規表現がネストに対応したのなんてもう一昔前ってイメージだけど なんでも正規表現で済まそうとするひとって
意地でもVBA使い続けてるひとと大差ない >>567
てか>>561には>>564のレスが既に付いてたじゃんか >>572
賢い人程手段をたくさん知り
その中から取捨選択するからな
>>571
さすがに勉強不足すぎだろw
何年前で知識止まってんだよ はいはい、正規表現マスターすごいねー
これでいいかな w 底辺に行くほど知識自慢はしかたがないだろ、正規表現に限らず
ただ掲示板的に質問したいのにバカがしゃしゃり出てきて迷惑だよな 的確な指示されても気に入らない回答だからと人の話を聴かない人は成長しないよ
自分の気に入る回答しかも自分と同じレベルの回答もらって喜んでればいい 俺なんか中学の勉強もロクにしなかったのに正規表現を理解したいから
今、大学レベルの数学を勉強してる・・なかなか進まないけどね・・
>>556 の質問からパーサとか出てくるのはちょっと違うと思うよ
metaタグ拾えばいいだけだよね?難しく考えすぎだよ
あとHTMLソースのほうが糞で実際の文字コードとmetaタグで指定されてる
文字コードが違うなんてことや、文字コードの指定が複数個所あるなんていう
2ページ分のHTMLをそのままくっ付けましたなんていうのも稀にあるから
そういう糞なHTMLを相手にする場合は対応を考えないといけないね >>579じゃあmetaタグを拾って来る正規表現をどうぞ 自分用に作るならこんな感じかなぁ、動作確認してないので使わないでね
|
<meta (?=\s) [^<>]* \s charset \s* = \s* (?:["']\s*)? ([^\s"'<>;]+)
|x;
こういうのは想定外 ※ " " の中に > がある
<meta comment="a>b" charset="UTF-8"> >>583
俺が書いた糞(>>559)より糞なコードが書かれて驚く
素直にパーサ使えよ >>583 のほうがスマートなのは一目瞭然でしょ
ただ >>583 は こんな感じ 程度のものなのでツッコミ所があっても知らないよ mataタグでのcharsetは定型的でしか使われないんで、仕様的に色々な場合に対応するのは無駄
俺が使うなら、こんなので十分
/<meta[^>]*\scharset=(["'])((?:(?!\1).)+)/i マッチングテスト
[1] <meta charset="UTF-8">
>>557 1. 失敗
>>559 マッチ
>>583 マッチ
>>586 マッチ
[2] このスレのHTML
557 1. マッチ
559 失敗
583 マッチ
586 失敗 こんなバカが回答者してたのか
過去レス見ると前から張り付いてるようだね bregonig.dll 2017/01/17 Ver.4.10 非包含オペレータに対応
うーん、非包含にマッチする正規表現はいつか自分で作れるように
なりたいと思ってたけど内部で勝手に作ってくれる時代になってしまったか〜
自分の知識は2013あたりで止まってるから浦島だ ■ このスレッドは過去ログ倉庫に格納されています