2014-01-10 19 views
1

我試圖在textfile中搜索正則表達式,而不是在匹配範圍內只用其他字符替換一個字符。我的問題是,我無法通過一些簡單的方法做到這一點。只替換正則表達式中的字符

示例源文件:

... 
<br> 
<a id="some shopitem" ref="#some shop item name 01 a" style="text-decoration:none;"><h3 style="background-color: #ccc;">blah blab hasdk sldk sasdas dasda sd</h3></a> 
<table> 
<td width="500"> 
.... 

有我需要匹配的正則表達式ref=\"#[[:alnum:] ]*\"(REF =「#不管用空格名稱」),並有將其替換空間中的比賽「 - 」,但當然不會改變另一個空格或正則表達式匹配。

所以結果應該看起來像這樣:

.... 
<br> 
<a id="some shopitem" href="#some-shop-item-name-01-a" style="text-decoration:none;"><h3 style="background-color: #ccc;">blah blab hasdk sldk sasdas dasda sd</h3></a> 
<table> 
<td width="500"> 
.... 

會做到這一點,而不只是在bash單行命令某種腳本它甚至可能嗎?有什麼方法可以取代組中的空間?像sed -r s/ref=\"#([[:alnum:] ]*\)/(\1s/ /-/g)/g'

回答

0

一個Perl的解決方案:

perl -pe 's/(ref="#)([\w\s]+)(")/ ($x,$y,$z)=($1,$2,$3); $y =~ s{\s}{-}g; $x.$y.$z /eg' 

它稍微寬鬆關於什麼可以在裁判的名字出現(下劃線,標籤,其他一些空格字符)

0

難道是甚至有可能做它沒有某種腳本只是在bash中的單行命令?

你的問題在某種程度上引發了一個燃燒的野心在我這樣做......!

varfile=SOURCEFILE && varsubstfile=RESULTFILE && IFS=' ' read -a repl <<< $(sed -r 's/(.*)(ref="#.*?")(.*)/\2/;tx;d;:x' $varfile | sed -e 's/\ /\-/g' | sed ':a;N;$!ba;s/\s/ /g') && for i in "${!repl[@]}"; do needle["$i"]=$(sed 's/\-/\ /g' <<< "${repl["$i"]}"); done && cp $varfile $varsubstfile && for i in "${!needle[@]}"; do sed -ir "s/${needle[i]}/${repl[i]}/g" $varsubstfile; done && unset needle && unset repl && less $varsubstfile && unset varfile && unset varsubstfile 

SOURCEFILE是你的資源文件,RESULTFILE是在輸出被寫入到一個文件名,所以要根據您的需要二者的改變。

嗯......這是怎樣的一個腳本,但它是一個(該死的巨大)的單行:)

我推測,也有ref="#.*"在整個文件中多個正好,否則它會一直更短(雖然我不記得更短的版本了)。

...我真的希望這個作品您的* nix系統上:d


以防萬一你想知道這件事情做什麼,這裏有一個解釋:

varfile=SOURCEFILE && #set variable for the sourcefile 
varsubstfile=RESULTFILE && #set variable for the resultfile 
IFS=' ' read -a repl <<< #we're going to read multiple values into an array "repl" 
         #delimited by a space 
    $(
    #grab only the second capture group (ref="#.*?") 
    sed -r 's/(.*)(ref="#.*?")(.*)/\2/;tx;d;:x' $varfile | 
    sed -e 's/\ /\-/g' | #replace every space in (ref="#.*?") with a dash 
    sed ':a;N;$!ba;s/\s/ /g' #replace newlines with a space 
    #when there is more than one occurence sed will delimit them with a newline 
    #but i set a space as the delimiter for the read operation, 
    #thus the last replacement 
    ) && 
#we now have every needed replacement-string in an array called "repl" 
for i in "${!repl[@]}"; do #iterate over every value in the array we just read 
    needle["$i"]=$(sed 's/\-/\ /g' <<< "${repl["$i"]}"); #replace dashes with spaces and store in a new variable 
done && 
#and now every original string, the needle we are going to search for 
#is stored in another array 
cp $varfile $varsubstfile && #copy sourcefile to resultfile 
for i in "${!needle[@]}"; do #for every string we are going to replace 
    sed -ir "s/${needle[i]}/${repl[i]}/g" $varsubstfile; #... we replace it! 
done 
#technically we're done here 
#but i like to clean up afterwards and show the result with less 
unset repl && less $varsubstfile && unset varfile && unset varsubstfile 
+0

驚人工作!很可惜,perl存在,所以可以更輕鬆地完成工作。我會將你的方式標記爲解決方案,因爲它令人印象深刻,你可以用bash來做到這一點。你有我的尊重人。 – Jan

+0

我只是爲了它的樂趣而做了這個,並且作爲概念的證明。這並不意味着它是一個「誠實的解決方案」,它只是表明只有bash纔有可能。這個該死的巨大事情幾乎是不可讀的,如果它不能按預期工作,將會很難進行調試;) –