2014-02-14 25 views
0

我有一條語句需要替換。原來的格式是這樣的:用shell腳本替換另一個語句

f.STRING.focus(); 

STRING[:alpha:][:digit:](正則表達式)的組合。 我的目的是將其更改爲

highlight("STRING"); 

例如:

f.abCDef12345.focus() --->  highlight("abCDef12345"); 
f.ip2.focus()   --->  highlight("ip2"); 

我可以輕鬆地使用sed更換聲明數百HTML文件。但是,我不知道如何在shell腳本中獲得STRING

過程可以描述如下:

For each html: 
    For the STRING which matches the pattern: 
     1. Assign it to a parameter. 
     2. Insert that STRING to highlight("STRING"); 
     3. Replace the old one "f.STRING.focus();" to "highlight("STRING");" 

但我不知道如何把它們寫在shell腳本...任何暗示表示讚賞。

更新時間:

  1. 請清楚地描述你的腳本。太謝謝你了!
  2. 抱歉的錯誤! STRING是和[:alpha:][:digit:]的組合。所以這裏提到的例子f.ip2.focus()可以說得通。
+0

你能不能只是在多個文件上使用sed和regexp?我不確定我是否正確地得到了這個想法。 – dstronczak

回答

2

試試這個辦法:

#!/bin/bash 

while read line 
do 
    sed 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' $line 
done < <(find . -type f -name '*.html') 

當你快樂與輸出改變沉渣 - 命令sed -i.bak,而不是做內聯替代。

說明:從當前文件夾下,並命名.html所有文件

  1. find命令遞歸搜索
  2. 一個bash而讀循環讀取一行在從find-輸出的時間命令
  3. sed然後用於搜索所需的模式,模式\(...\)被稱爲標題組,它將匹配的文本存儲在一個變量中,該變量可以使用稱爲反向引用的\1進行訪問。

閱讀和在bash文件中的每一行操作的正確的方法是使用

while read line 
do 
    echo $line 
done < file 

在我們的例子中,我們沒有一個文件,而不是我們想要在命令輸出的每一行上操作,請輸入process substitution<(...)您當然可以使用重定向將find-command重定向到文件find ... > file,然後對其執行操作。

更新

正如@tripleee while循環指出,可以完全被丟棄:

sed -i.bak 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' $(find . -type f -name '*.html') 

sed '...' $(find...)結構中$()執行部分子shell,提供所有匹配文件作爲參數sed命令如下所示

sed '...' ./c/file.html ./a/file.html ./b/file.html ./d/file.html 

如果你有很多html文件,shell可能會因爲命令行太長而引發錯誤;如果是這樣的話xargs是你的朋友(man xargs)。

..或者(Linux滿了TMTOWTDI),讓find爲所有匹配的文件(一次一個)執行sed-part,這樣你就不會冒着獲得太長命令行的問題:

find . -type f -name '*.html' -exec sed 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' {} \; 
+0

我不知道爲什麼我應該在'[:alpha:]'周圍添加'括號'和'(「\ 1」)'究竟是什麼意思? 另外,對不起,我無法弄清楚最後一句'done < Stallman

+0

查看更新,它有幫助嗎? –

+0

我仍在嘗試,謝謝。 – Stallman

0

sed -i 's/b.\(STRING\).focus()/highlight("\1")/g' file會做的伎倆

#echo "b.STRING.focus()"| sed 's/b.\(STRING\).focus()/highlight("\1")/g' highlight("STRING")

+0

你可以給你的代碼添加一些解釋嗎?我完全無法得到它。 – Stallman

+0

基本上,正如所有其他人所說,在sed表達式左邊的括號之間的表達式可以通過在右邊使用\#來恢復 –

0

awk版本:

echo 'f.STRING.focus("Some data")' | awk '{gsub(/[[:alpha:]]\.[[:alpha:]]+\.focus\(/,"highlight(")}1' 
highlight("Some data") 

使用sed

echo 'b.STRING.focus("Some data")' | sed 's/[[:alpha:]]\.[[:alpha:]]*\.focus/highlight/g' 
highlight("Some data") 
2
sed -i 's/f\.\([a-zA-Z0-9]\+\)\.focus()/highlight("\1")/g' file_to_process 
  1. f\.匹配f.
  2. \([a-zA-Z0-9]\+\)匹配的一個或多個字母數字字符,並存儲在變量匹配STRING1
  3. \.focus()匹配.focus()
  4. highlight("\1")替換整個匹配模式與給定的文本和可變1值 - >higlight("STRING")
+0

不符合提供的測試字符串'abCDef12345' –

+0

也許是因爲':alpha:'是'a-z A-Z'而已? – lukk

+0

當然需要使用'[A-Za-z0-9]' –

0

你可以使用這個sed的:

sed -i.bak 's/f\.\([[:alnum:]]\+\).focus()/highlight("\1")/g' file.html 

這裏sed的是找到

f.<string-with-1-and-more-alpha-numerics>.focus() 

並捕獲中間部分爲相匹配的組#1

它正在取代以:

highlight("\1") 

其中「\ 1`是反向引用的匹配組#1