2017-10-07 47 views
1

我工作的一些非常凌亂Excel表格,並試圖使用PHP來尋找線索..PHP的preg_replace:找到字符串的一部分不帶感嘆號

我有從Excel中的所有公式MySQL數據庫開始文檔,並且像往常一樣,當前工作表的單元名稱沒有「工作表名稱」!在它前面。爲了使它成爲可搜索的(並且在公式中找到死路由),我喜歡用它們的sheetname替換數據庫中的所有公式作爲前綴。

實施例:

=+(sheet_factory_costs!A17/sheet_employees!D23)+T12+W12 

該數據庫包含的當前表的名稱,以及我喜歡與SHEETNAME改變上述公式(我們稱之爲「sheet_turnover」)。

=+(sheet_factory_costs!A17/sheet_employees!D23)+sheet_turnover!T12+sheet_turnover!W12 

我嘗試這個PHP中的preg_replace,我想我需要以下規則:

  1. 找到一個或兩個字母,直接跟着一個數字。這通常是公式中的單元格地址。
  2. 什麼時候有!在之前的位置上,已經有一個工作表名稱。所以我只是在尋找不以感嘆號開頭的字母和數字。

問題似乎是!也是模式內的特殊符號。即使我試圖逃避它,它不工作:

$newformula = 
preg_replace('/(?<\!)[A-Z]{1,2}[0-9]/', 
'lala', 
$oldformula); 

(拉拉是我的臨時標誌,看它是否是選擇合適的細胞不會忽略)

(是的,拉拉是唯一在第一號的地方,但是這是沒有問題現在)

(是的,所有的Excel $ .. $ ..(永久)標記已經被替換,無需建立一個公式中)

+0

您需要將反斜槓加倍,因爲它在字符串文字中具有轉義含義,可以「吃」它們。 – trincot

+0

實際上,'(?<\!)'在PCRE中是一個無效的regex構造,如果您嘗試它,您會收到關於不完整的組結構的警告。這不是關於這裏需要多少逃避反斜槓。 –

回答

0

你的消極lookbehind是腐敗的,你需要將其定義爲(?<!!)。但是,您還需要使用前面的單詞邊界,或者使用後視圖以確保[A-Z]{1,2}之前沒有其他字母。

所以,你可以使用

'~\b(?<!!)[A-Z]{1,2}[0-9]~' 

regex demo。替換爲sheet_turnover!$0,其中$0是整個比賽值。

詳細

  • \b - 一個字邊界(這是必要的,或name!AA11仍然會得到匹配)
  • (?<!!) - 立即無!到當前位置的左邊
  • [A-Z]{1,2} - 1或2個字母
  • [0-9] - 一個數字。

另一種方法是匹配,並跳過「錯誤」的情境,然後匹配,並保持「正確」的人:

'~\w+![A-Z]{1,2}[0-9](*SKIP)(*F)|\b[A-Z]{1,2}[0-9]~' 

this regex demo

這裏,\w+![A-Z]{1,2}[0-9](*SKIP)(*F)|部分匹配1個或多個單詞字符,然後1個或2個大寫ASCII字母,然後一個數字,(*SKIP)(*F)會忽略了比賽,將會使發動機繼續尋找以前的比賽結束後,比賽。

+0

這使感嘆號加倍了。我不明白爲什麼我必須這樣做,但它工作正常。 有或沒​​有/ b的結果沒有差異。如果沒有/ b,它不會影響之前的單詞(表單名稱): old:= + D16 +(P25 /(O25 *(Entry_machines!C12))) 新:= + lala6 +(lala5 /(lala5 *(Entry_machines !)C12))) –

+0

@TwomuchTime我寧願你在'(!<!...)'(負反向)構造中將它當作'!'處理。然後,它變得非常清楚。 –

+0

@TwomuchTime如果列名中有兩個字母,'\ b'將會有所不同。嘗試對照+ D16 +(P25 /(O25 *(Entry_machines!CC12)))' –