> ここは素直に,量指定子の使える新しいgrepにした方がいいような気がするのですが…。
> でも2段階は許容できないんですよね,としきさんとしては。
ずるいPerlな正規表現を使った場合(というか、それしかないはず…)。 [^0-9]の否定は、それ自体で1字喰ってしまうのが面倒なのだと思う…。 [^], [$]って、メタキャラの意味になりませんよね。 まったく自信がありません。 まぐれで「それっぽい」結果になった可能性大です。 --- t.grp --- regex 定義ファイル(コマンドラインだとオアがおいたをするかも?) (?<!\d)2\d{4}(?!\d|/) ------------- --- test.txt --- 対象テスト・ファイル 20000 200000 20000 20000/ 200000 320000 32000 --------------- --- コマンドライン&結果 --- C:\>yagrep -ft.grp -P test.txt |to 20000 20000 ---------------------------- --- 鬼車定義 --- \d decimal digit char (?=subexp) look-ahead (?!subexp) negative look-ahead (?<=subexp) look-behind (?<!subexp) negative look-behind ----------------
> ずるいPerlな正規表現を使った場合(というか、それしかないはず…)。
泥縄ですねぇ。としきさんの3段階に漏れや拾いすぎがないなら(そう 見えましたが)、あれがスマートっぽいです。>「20000/20001」というパターンが行頭にある場合は除外する>けど、そうでないときは引っかかってほしい。 あ、でも、この場合「20001」の>ほうで引っかかってくるのか。ということを考えると、むちゃくちゃ面倒なので、た、確かに、これはむちゃくちゃ面倒ですねぇ。 あとでsedで削りましょう(※)。 --- t.sed --- #onigsed -R(分かんなくなるから、perlモードで) /1\d{4}\/2\d{4}/d ------------- (勝手に「1万台の番号/2万台の番号」と決めた。でも考えてみたら、こんなこと あまり気にしないほうがようですね。そんなのあんまりしないでしょう。ヘッダもろ ともタイプか…。ぶ、文太だ。)>「29999/30001」というパターンが行頭にある場合は引っかからず、引用符>つきの場合なら引っかかる、くらいにしておきますか。継ぎ足し、しました。 --- t1.grp --- (?<!\d)2\d{4}(?!\d|/) -------------- --- t2.grp --- [^0-9]2\d{4}(?!\d) -------------- --- コマンドライン --- C:\>yagrep -ft1.grp -P test.txt >kek.txt C:\>yagrep -ft2.grp -P test.txt >>kek.txt C:\>onigsed -ft.sed -R kek.txt >result.txt ---------------------- たぶん、sedで1つのスクリプトにするのが…。 下も、自信ないですが。 --- t.sed --- #>Onigsed -R -ft.sed test.txt |to /(?<!\d)2\d{4}(?!\d|\/)|[^0-9]2\d{4}(?!\d)/{ /1\d{4}\/2\d{4}/d b} d ------------- 簡単な解説。 /A|B/ {/C/d;b} d のような形。 AとBのオアの条件。条件クリアならさらにCの条件。Cクリアならdelして branch(分岐先がないので。ここから脱出し、また、最後のdelもしない)。 上のA,Bをそもそもクリアできないど、自動del(sedは何もしないと全部 プリントしてしまうから)。 Aは文頭・文末を含めた2万台の5桁数字。20000/の「/」付きも駄目。 Bは、引用符がある場合。「/」付きを許す。 Cは、19999/20000のように、後ろの2万台がヒットした場合。del。 b (branch)では、Cでdelされようがされまいが、スクリプト末へジャンプ。 --- test.txt --- 29999/30001 拾うな>29999/30001 拾え19999/20000 拾うな>19999/20000 拾うな29999 拾え 29999 拾え>29999/3000129999 29999 ----------------最後の3行は、文末用(?) --- 結果 --- C:\>Onigsed -R -ft.sed test.txt |to>29999/30001 拾え29999 拾え 29999 拾え>29999/3000129999 29999 ------------ あ、たぶん、1行にヒットしたりするのが複数あると、やはりミスはあるで しょう。拾えないという痛いのもあるでしょうね。(※とリンク) /(?<!\d)2\d{4}(?!\d|\/)|[^0-9]2\d{4}(?!\d)/{ b} としておいたほうがよさそう。これで、複数ヒット対策は…??? 防災と同じで、漏れるより拾い過ぎが良いでしょうね。 以上です。
としきさん>やっぱり、むちゃくちゃというか、私の理解の範囲を超えつつあります。>数学の各種未解決問題のような感じになってしまいました。現実的にはこの問題は難しいですが、僕の半端解が難しそうに見えるのは、 たぶん、sedのコーディング(コマンドとロジック)のせいでしょう。>発端は、なんか簡単な解があるのではないか、というところだったんですがね。正規表現って、ツールのコマンドとの兼ね合いの部分もありますから。 でも、文頭・文末、否定、桁数指定。この条件で「簡単な解」はないと思う。 文頭、文末の例外を拾うとしきさんの3行は明晰。僕がちゃんと読めないくらい 論理的でしたが。>ま、あまり本気にならずに、でも、ふとひらめいたりしたら本気になっちゃった、というか、予想外にサクサクいったのです。「絶対ムリ」 と最初思ったから。すると、現実には、どの程度で妥協するかになり、手を動かし てやってみるしかない、となるのですよねぇ…。漏れは見えないけど…。 ではでは。