質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

4回答

6997閲覧

正規表現で『「abc」と言う塊以外の文字列』は指定できるか

uer03108

総合スコア194

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

2グッド

9クリップ

投稿2016/03/29 13:17

編集2016/04/04 09:18

正規表現について、質問です。

例えば、下記の様な文字列を考えます。

aeeebbdddabccccffff

この時、正規表現が

reg = "/[^abc]+/";

であれば、「a, b, c」以外になるので、

res = "eeedddffff";

になります。

質問なのですが、『「abc」と言う塊以外の文字列』は指定できるのでしょうか。

preStr = "aeeebbddd「abc」cccffff";

resStr = "aeeebbdddcccffff";

となる様な正規表現になります。


補足

多くの回答、有難うございました。
読み返してみると言葉足らずでしたので、補足させて頂きます。
恐らく、CertaiN様の方法でいけそうな気がします。

正直に言うと、CodeIQであった問題です。
頭に引っかかっていたので質問させて頂きました。

例えば、
I am Tom. He is Mr. Smith.

と言う文章が1行であるとします。
この文章を

I am Tom.
He is Mr. Smith.

の2つに分ける場合、単純に「.」でsplitするとMr.の部分も分割されてしまいます。
なので、
「Mr.」は除いて、「.」で分ける
と言う処理が必要になりますが、
/[^Mr.]+[.]/
にすると、質問の通り上手く動作しません。なので、「Mr.」と言うブロックを除く処理が調べておりました。

mpyw, ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

まず前提として,この回答においては文字列ではなくバイト列という表記にします.日本語を相手にしても本当に1文字という単位で見てくれるのはu修飾子をつけたpreg_*系の関数,あるいは文字コードをUTF-8として正しく指定したmb_*系の関数のみです.残りの関数は全てバイト単位で計算します.

本題に入ります.既に回答にありますが,除外したいバイト列を空白に置換して残ったバイト列を得るというアプローチにてpreg_replaceあるいはpreg_replace_callbackを使って済むのであればそれが一番簡単です.正規表現無しでも簡単に書ける範囲であればstr_replacestrtrを使うほうがよいでしょう.なお文字コードがUTF-8である場合は,正規表現の文字クラス[]を使わない限り,「文字列=バイト列」のように扱っても正しく動作します.このことは上にリンクしたQiitaの記事でも解説しています.

php

1<?php 2 3$str = 'ライスパスタカレーパスタドリア'; 4 5echo str_replace('パスタ', '', $str), "\n"; // ライスカレードリア

但しこれらには,複数の置換を同時に行う際に微妙な違いがあるので注意してください.以下を実行してみるとわかります.

php

1<?php 2 3$str = 'ライスパスタライスカレーライスカレードリア'; 4 5print_r([ 6 7 'str_replace' => str_replace( 8 ['カレーライス', 'カレー', 'ライス'], 9 ['【カレーライス】', '【カレー】', '【ライス】'], 10 $str 11 ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア 12 13 'strtr' => strtr($str, [ 14 'カレーライス' => '【カレーライス】', 15 'カレー' => '【カレー】', 16 'ライス' => '【ライス】', 17 ]), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア 18 19 'preg_replace (複数の正規表現で処理)' => preg_replace( 20 ['/カレーライス/', '/カレー/', '/ライス/'], 21 '【$0】', 22 $str 23 ), // 【ライス】パスタ【ライス】【【カレー】【ライス】】【カレー】ドリア 24 25 'preg_replace (単一の正規表現で処理)' => preg_replace( 26 '/カレーライス|カレー|ライス/', 27 '【$0】', 28 $str 29 ), // 【ライス】パスタ【ライス】【カレーライス】【カレー】ドリア 30 31]);

**strtr preg_replace (単一の正規表現で処理) においては一度置換したところを次回の置換対象から外してくれますが, str_replace preg_replace (複数の正規表現で処理) においては全く考慮してくれません. **速度面においても,僅かな違いですが,一般的には速い順に

  1. str_replace
  2. strtr (実はもう1つ使い方があるがこの例のように連想配列で置換する場合)
  3. preg_replace (単一の正規表現で処理)
  4. preg_replace (複数の正規表現で処理)

として差がつくと思うので,書きやすさも考慮して適宜使い分けてください.

また正規表現の高度なテクニックですが,バックトラッキングコントロールを使うとまさに**「あるバイト列以外のバイト列」**を直接マッチさせることもできます.

php

1<?php 2 3$str = 'ライスパスタライスカレーライスカレードリア'; 4 5echo preg_replace( 6 '/(?:カレー|ライス)(*SKIP)(*FAIL)|.+?(?=カレー|ライス|\z)/s', 7 '【$0】', 8 $str 9), "\n"; // ライス【パスタ】ライスカレーライスカレー【ドリア】

上記の例では

  1. まず現在位置から「カレー」「ライス」いずれかにマッチするバイト列を探す.**マッチしたら何も無かったことにして3に進む.**マッチしなければ2に進む.
  2. 後ろに「カレー」「ライス」「末尾」のいずれかが来るように,1バイト以上の可能な限り短いバイト列を探す.マッチしたら置換処理を行う.マッチしなければ3に進む.
  3. 現在位置を今マッチさせたバイト列のぶんだけ進める.マッチしていなければ1バイト進める.
  4. まだ後ろに1バイト以上あれば1に戻る.無ければ終了する.

という処理を行っています.


【追記】

コメントにも書きましたが,こちらにも最終目的のコードをシンタックスハイライトをつけて書いておきます.

php

1<?php 2 3$str = 'I am Tom. He is Mr. Smith.'; 4$sentences = preg_split('/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/', $str); 5var_dump($sentences); 6 7/* 8array(2) { 9 [0]=> 10 string(9) "I am Tom." 11 [1]=> 12 string(16) "He is Mr. Smith." 13} 14*/

投稿2016/03/29 15:38

編集2016/03/31 10:04
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2016/03/31 03:40

勉強になりました。 有難うございます。
mpyw

2016/03/31 09:46

補足拝見しました.strtrで Mr. → Mr. を入れておくか,preg_replace で Mr\.(*SKIP)(*FAIL) を入れておけばいけそうですね.
mpyw

2016/03/31 10:04 編集

求められる処理は置換というより分割なので,preg_splitのほうがいいかもしれません.もう1つ高度なテクニックである置換位置のリセット \K も使いますが,これを使って $str = 'I am Tom. He is Mr. Smith.'; $sentences = preg_split('/(?:Mr|Mr?s|Dr|Sir|Prof)\.(*SKIP)(*FAIL)|\.\K\s+/', $str); で望んだ通りの結果が得られると思います.
guest

0

res = "eeedddffff";
になります。

なりません。
/[^abc]+/ というパターンで "aeeebbdddabccccffff" を検索したら "eee" が引っかかります。

言いたいことはそういうこでではないのでしょうか? "aeeebbdddabccccffff"に対して/[^abc]+/というパターンをどういう風に適用すると"eeedddffff"というテキストが得られるのでしょうか。まずはそこからです。

投稿2016/03/29 13:39

yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

/abc/ で期待した値が得られると思いますが。間違ってたら、すいません。

  • Code
$pattern='/abc/'; $replacement=''; $string='aeeebbdddabccccffff'; echo preg_replace($pattern, $replacement, $string);
  • result
aeeebbdddcccffff

投稿2016/03/29 14:06

JinwonKim

総合スコア312

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

aeeebbdddabccccffffこの時、正規表現がreg = "/[^abc]+/";

であれば、「a, b, c」以外になるので、res = "eeedddffff";になります。

「aeeebbdddabccccffff」に「reg = "/[^abc]+/";」で検索かけると、HITするのは「eee」と「ddd」と「ffff」だと思いますよ。
regの意味は「a」でも「b」でも「c」でもない文字一文字以上の連続した塊です。

preStr = "aeeebbddd「abc」cccffff";

resStr = "aeeebbdddcccffff";
となる様な正規表現

条件に一致する塊を検出するものですから、間を抜いた文字列を正規表現だけで直接取り出すことは出きません。単にresStrを得たいだけなら「abc」を検出して、これを空白に置換してしまえば良いのではないでしょうか?

投稿2016/03/29 13:42

編集2016/03/29 13:46
hirohiro

総合スコア2068

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問