2013-03-20 70 views
1

我有一個用例,我想用一個空格替換多個空格,除非它們出現在引號內。例如如果多個空格不在引號之間出現,請用單個空格替換多個空格?

原始

this is the first a b c 
this is the second "a  b  c" 

this is the first a b c 
this is the second "a  b  c" 

後,我相信一個正則表達式應該能夠做的伎倆,但我沒有與他們太多的經驗。下面是一些代碼,我已經有

import re 

str = 'this is the second "a  b  c"' 
# Replace all multiple spaces with single space 
print re.sub('\s\s+', '\s', str) 

# Doesn't work, but something like this 
print re.sub('[\"]^.*\s\s+.*[\"]^, '\s', str) 

我明白了爲什麼我的第二個以上不工作,所以只是想一些替代方法。如果可能的話,你能解釋一下你的regex解決方案的一些部分嗎?由於

+0

你有這樣的事情:'asdasdasd「asdasdasd ____ asdajskd」'('_'代表空格)。你只用空間工作,還是你也想處理新的行? – nhahtdh 2013-03-20 17:06:29

+0

是的。裏面的引號可以是任何東西,它應該被忽略 – Shane 2013-03-20 17:09:39

+0

'裏面的引號可以是任何東西'它可以包含新行嗎? – nhahtdh 2013-03-20 17:11:59

回答

1

"substring"

import re 
str = 'a b c "d e f"' 
str = re.sub(r'("[^"]*")|[ \t]+', lambda m: m.group(1) if m.group(1) else ' ', str) 

print(str) 
#'a b c "d e f"' 

正則表達式("[^"]*")|[ \t]+中假設沒有"將匹配帶引號的字符串或一個或多個單空格或製表符。由於正則表達式首先匹配帶引號的子字符串,因此它內部的空白字符將無法與替代子模式[ \t]+匹配,因此將被忽略。

與引用的子字符串匹配的模式包含在()中,因此回調可以檢查它是否匹配。如果是這樣,m.group(1)將是truthy,它的價值只是返回。如果不是,則匹配空白,因此單個空間作爲替換值返回。

沒有LAMDA

def repl(match): 
    quoted = match.group(1) 
    return quoted if quoted else ' ' 

str = re.sub(r'("[^"]*")|[ \t]+', repl, str) 
0

如果你想一個解決方案,可靠的每一次努力,無論輸入或其他警告如不使嵌入式報價,那麼你要編寫一個簡單的解析器不使用正則表達式或者用引號分割。

def parse(s): 
    last = '' 
    result = '' 
    toggle = 0 
    for c in s: 
     if c == '"' and last != '\\': 
      toggle ^= 1 
     if c == ' ' and toggle == 0 and last == ' ': 
      continue 
     result += c 
     last = c 
    return result 

test = r'" < >"test 1 2 3 "a \"< >\" b c"' 
print test 
print parse(test) 
相關問題