2017-02-01 19 views
3

私は、行の先頭にある4つのスペースをタブに置き換えることを検討していますが、テキストが存在するときはそれ以上のものを置き換えたくありません。スペースの字下げをタブで置き換える

読みやすさのために私の最初の正規表現/ {4}+/または/[ ]{4}+/がはっきりと働いていますが、明らかに4つのスペースで見つかったインスタンスは置き換えられます。

$string = '  this is some text --> <-- are these tabs or spaces?'; 
$string .= "\n and this is another line singly indented"; 
// I wrote 4 spaces, a tab, then 4 spaces here but unfortunately it will not display 
$string .= "\n \t and this is third line with tabs and spaces"; 

$pattern = '/[ ]{4}+/'; 
$replace = "\t"; 

$new_str = preg_replace($pattern , $replace , $string); 

echo '<pre>'. $new_str .'</pre>'; 

これは、式は、変換に関して完璧に動作しますが、----> <の間に4つのスペース、その事実のために与えられた正規表現を使用して、私がもともと持っていたものの一例でした----タブで置き換えられます。私はインデントを変更していないテキストを実際に探しています。

私の最善の努力は、これまでのラインの(^)スタート([ ]{4}+)最初の非空白ゴマ\s

ほとんど動作しますが、ために...

$pattern = '/^[ ]{4}+.*?[;\s]*/m';

アップパターン(.*?[;\s]*)何もしていインデントが失われているという事実は、私がここで紛失しているものを誰にでも理解できるようにすることができますか?

[編集]私がやろうとしています何を明確にするために

が、これは誰にも混乱し、なぜ、私は本当に理解していないタブのスペースからテキストのインデントの開始を変更です。 (上記$stringの値を使用して)できるだけ明確にすること

First line has 8 spaces at the start, some text with 4 spaces in the middle. 
I am looking for 2 tabs at the start and no change to spaces in the text. 

Second line has 4 spaces at the start. 
I am looking to have only 1 tab at the start of the line. 

Third line has 4 spaces, 1 tab and 4 spaces. 
I am looking to have 3 tabs at the start of the line. 
+0

私は多分何かが欠けている。唯一のタブと4つのスペースの交換について質問です、またはあります – Niitaku

+0

'preg_replace( '〜(?:^ | \ G)[] {4}〜m'、 '\ t"、$ s) 'を試してみてください、https://ideone.com/EzjRYCをご覧ください。 –

+0

@WiktorStribiżewこれはまだそれの真ん中にタブで3行目に対処していません – Lucas

答えて

0

あなたが正規表現の第一人者でないなら、これはおそらくあなたに最も意味をなさないとに適応しやすくなります同様のユースケース(これは、最も効率的なコードではありませんが、それはほとんどの「読み」私見です):

// replace all regex matches with the result of applying 
// a given anonymous function to a $matches array 
function tabs2spaces($s_with_spaces) { 
    // before anything else, replace existing tabs with 4 spaces 
    // to permit homogenous translation 
    $s_with_spaces = str_replace("\t", ' ', $s_with_spaces); 
    return preg_replace_callback(
     '/^([ ]+)/m', 
     function ($ms) { 
      // $ms[0] - is full match 
      // $ms[1] - is first (...) group fron regex 

      // ...here you can add extra logic to handle 
      // leading spaces not multiple of 4 

      return str_repeat("\t", floor(strlen($ms[1])/4)); 
     }, 
     $s_with_spaces 
    ); 
} 

// example (using dots to make spaces visible for explaining) 
$s_with_spaces = <<<EOS 
no indent 
....4 spaces indent 
........8 spaces indent 
EOS; 
$s_with_spaces = str_replace('.', ' '); 
$s_with_tabs = tabs2spaces($s_with_spaces); 

あなたがパフォーマンスしたが、ハードディスクの代わりにワンライナーを理解したり、微調整したい場合は、コメント欄でのソリューション上記の正規表現 - gurusから作業する必要があります:)


P.一般にpreg_replace_callback(およびits equivalent in Javascript)は、構造化テキスト処理の優れた「スイス軍ナイフ」です。私は、恥ずかしがり、それを使用してミニ言語に執筆パーサーを持っている;)

+0

残念ながら、残念ながらこれは3行目(2つのタブを表示してから4つのスペースを表示)で不足しています。他の言語にも引き継ぐように正規表現を使用するのが本当に好きです。 – Lucas

+0

@ルーカあなたは3行目でも動作するように変換を行う前に、既存のタブをすべてスペースで置き換えることができます(後でタブを避けたい場合は、この変換をregexベースにすることもできます)。私は少なくともこれを解決するために私の解決策を更新しました。私は "monter regexes"に対してアドバイスします:コードレビューで見つけたときはいつでも、より多くのコード(とコメント)+シンプレregexesを使うか、可能であればregezesを使うか、最悪の場合は、より大きなregexをそれらの間の十分なコメントを持つより小さい文字列 - コード可読性以上: – NeuronQ

0

私はそれをする方法です。

$str = "..."; 
$pattern = "'/^[ ]{4}+/'"; 
$replace = "\t"; 

$multiStr = explode("\n", $str); 
$out = ""; 
foreach ($multiStr as &$line) { 
    $line = str_replace("\t", " ",$line); 
    $out .= preg_replace($pattern , $replace , $line) 
} 

$results = implode("\n", $out); 

私は迅速かつ直感的な方法でこれを行っている徹底的ように、コードを再評価してください。

私はそれをテストするためのPHPサーバーを実行することはできません:(しかし、あなたは、この問題を解決に役立つはず通り。

+0

公開PHPサーバ、https://3v4l.org/、https://eval.in/。 – chris85

関連する問題