2017-11-22 13 views
9

私は固執しています - ここではたくさんの回答を見てきましたが、最後の問題は解決しないようです。略語を省略してPHPで読むことができるように書式を設定する

JSONのAPIを使用して、キャメルケース形式の機器リストを受け取ります。私はそれを変えることはできません。

私はこのキャメルケースは、通常の言語に翻訳する必要がある -

これまでのところ、私が得ているほとんどの言葉は通じ区切ら:

$string = "SomeEquipmentHere"; 

$spaced = preg_replace('/([A-Z])/', ' $1', $string); 
var_dump($spaced); 

string ' Some Equipment Here' (length=20) 

$trimmed = trim($spaced); 
var_dump($trimmed); 
string 'Some Equipment Here' (length=19) 

正常に動作している - しかし、機器の一部に省略形で構成されてい

「ABSBrakes」 - これが必要となるABSとブレーキ

私はEACの隣にあるいくつかの大文字のためにチェックすることはできませんから分離それはその後、ABSとブレーキを一緒に保持しますので、他の時間 - つまり、より多くのこれらのようにあります:「CDRadio」

だから出力がためにされて欲しいものです:

"ABS Brakes" 

はフォーマットする方法がありますそれで、大文字が隣にある場合は、そのシーケンスの最後の大文字の前にスペースを追加するだけですか?

私は正規表現では強くありません。

どちらの貢献は素晴らしいです

EDIT - 後でここに来る人は、両方の答えに

を読むべき構成されていた最後の問題は、次のパターンです:

「ServiceOKは、」「サービスOK」となり

"ESP"が "ES P"になる

パターン純粋な大文字の略語のみで構成され、小文字の文字をカウントする関数で固定されています。存在しない場合は、preg_replace()をスキップします。

しかし、フライングは彼の答えのコメントに書いているように、潜在的に彼の正規表現でカバーされていないインスタンスがたくさんある可能性があり、答えが不可能である可能性があります - これは正規表現。

おそらくルール「大文字の後に小文字がない場合は、スペースが挿入されてはならない」いくつかを追加することにより

ここ
+0

すべての深刻なAPIは、識別子(数値またはキャメルケースオブジェクト名)と「表示名」を送信する必要があります。回避策の他に、APIの所有者に連絡して、不足している情報を入力するように依頼します。 – DanFromGermany

+0

@DanFromGermanyこれは本当です...しかし、彼らからのアクセスを得るのにおよそ1週間かかりましたので、いつでもすぐに修正されるのではないかと疑います。 – Stender

答えて

2

ここでは、置換文字列内の任意のアンカー、キャプチャグループ、または参照を使用していないシングル呼び出しパターンです:/(?:[a-z]|[A-Z]+)\K(?=[A-Z]|\d+)/

Pattern&Replace Demo

コード:(Demo

$tests = [ 
    'SomeEquipmentHere', 
    'ABSBrakes', 
    'CDRadio', 
    'Valve14', 
]; 
foreach ($tests as $test) { 
    echo preg_replace('/(?:[a-z]|[A-Z]+)\K(?=[A-Z]|\d+)/',' ',$test),"\n"; 
} 

出力:

Some Equipment Here 
ABS Brakes 
CD Radio 
Valve 14 

これは、モップアップするものがないため、これはより良い方法です。考慮する新しい文字列がある場合(私のメソッドを壊す)、私のパターンを更新できるようにコメントにそれらを残してください。

パターンの説明:

/   #start the pattern 
(?:[a-z] #match 1 lowercase letter 
|   #or 
[A-Z]+) #1 or more uppercase letters 
\K  #restart the fullstring match (forget the past) 
(?=[A-Z] #look-ahead for 1 uppercase letter 
|   #or 
\d+)  #1 or more digits 
/  #end the pattern 

編集:を含む優れた精度を提供する他のいくつかのパターンがあります

:確か

/(?:[a-z]|\B[A-Z]+)\K(?=[A-Z]\B|\d+)/ 

は、上記のパターンではなく適切になりますハンドルServiceOK

Demo Link


​​又はアンカーこのパターン:

/(?!^)(?=[A-Z][a-z]+|(?<=\D)\d)/ 

上記パターン意志正確スプリット:SomeEquipmentHereABSBrakes、OPによって要求されるようCDRadioValve14ServiceOKESP

Demo Link

*注:複数のサンプル列が設けられているように、パターン精度を向上させることができます。

+0

@Stenderこれは楽しいものでした。私はすべての提供された入力に作用するよりクリーンな方法をあなたに提供しました。パターンが正しく処理できない新しい入力がある場合は、質問に追加してコメントを残してください。私に何かもっと説明してもらいたいなら、ただ聞いてください。 – mickmackusa

+0

これは非常にきれいに見えます!私は修正可能かどうかわからない新しいパターンの問題があります - 基本的に:大文字の後に小文字がない場合、スペース( ' - ')を挿入してはいけません - 質問を更新しました – Stender

+0

このように:https://regex101.com/r/TNZNC0/2?あなたが私に与える文字列が多いほど、パターンを洗練することができます。 – mickmackusa

3

は、それが解決することができる方法です。

$tests = [ 
    'SomeEquipmentHere', 
    'ABSBrakes', 
    'CDRadio', 
    'Valve14', 
]; 
foreach ($tests as $test) { 
    echo trim(preg_replace('/\s+/', ' ', preg_replace('/([A-Z][a-z]+)|([A-Z]+(?=[A-Z]))|(\d+)/', '$1 $2 $3', $test))); 
    echo "\n"; 
} 

関連のテストにregex101

UPDATE:追加の質問を追加しました例

+0

これはまさに探していたものです!あなたはSir/Mamが素晴らしいです - これは質問の一部ではないことを知っていますが、文字列の最初の数字の前のスペースのように正規表現に何かを追加できますか? Valves14のようなものも間隔を置くことができますか? – Stender

+0

@Stenderそれはちょっと違うアプローチですが、そのような文字列の解決策を提供するために答えを更新しました – Flying

+0

私はそれを間違って読んでいますか、今は "AB SB rakes"を正規表現テストで返していますか? – Stender

関連する問題