2014-02-14 26 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