我有以下结构的文件:
foo.bar.baz () ->
templateUrl: require('x.jade')
我需要转换这些文件以便:
- 它们的前缀是
var templateUrl = require('x.jade')
- 该
templateUrl:
行被替换为templateUrl: templateUrl
。
我该怎么做?一个选项是针对每个文件使用 bash 脚本:
grep
以templateUrl:
获得该require
部件。cat
将该var templateUrl
行和文件一起合并为一个新文件,然后替换原文件。- 用来
sed
代替。templateUrl: require...
templateUrl
但是,可以通过针对每个文件执行的单个脚本sed
来实现这一点吗?awk
答案1
@simlev 的perl
解决方案确实步骤较少,但我想介绍一下我的sed
命令。这更有意义,因为 OP 已经设想使用sed
并明确要求使用sed
或awk
脚本。
sed -n '1h;:a;n;s/require/&/;tInsert;H;ba;:Insert;H;s/^/var/;s/:/ =/;G;s/: .*/: templateUrl/;p'
笔记:如果文件包含多行带有:
或 的行,此命令将不起作用require
。
解释:
sed -n # -n option disables automatic printing.
1 h # h command puts the first line (address 1) in the hold space,
# replacing any previous content.
:a # Set a mark with label 'a'.
n # n command prints the pattern space and loads next line of input,
# replacing all pattern space content.
# But it will not print because of -n option.
s/require/&/ # Test if the pattern space has the line OP wants edit.
t Insert # If substitution was made, t command jumps to the mark with label 'Insert'.
H # If not, continue with H command, it appends a '\n' to the hold space content
# and then appends the pattern space to the hold space.
b a # b (branch) command, jumps to the mark with label 'a'.
:Insert # Exit from the 'a' loop. Here the hold space has all the lines that precede
# the line with 'replace', and pattern space has the line with 'replace'.
H # The line with 'replace' is appended to the hold space too.
s/^/var/ # Here sed finally edits the line, replacing the beginning with 'var' ...
s/:/ =/ # and only the first ':' with ' ='.
G # G command appends the content of hold space to the edited pattern space,
# here that line edited above in pattern space becomes the first line.
s/: .*/: templateUrl/ # One more substitution.
p' # Finally, print the pattern space.
答案2
输入文件:
foo.bar.baz () ->
templateUrl: require('x.jade')
perl
命令:
perl -i -0777pe '$_=~s/templateUrl:( \K.*)/templateUrl/;print"var templateUrl =$1\n"' *
输出文件:
var templateUrl = require('x.jade')
foo.bar.baz () ->
templateUrl: templateUrl
分解:
perl
擅长文本处理的脚本语言-i
就地编辑文件-0777
对整个文件进行处理,而不是逐行处理p
打印文件(在这种情况下,由于-i
切换,文件将被保存)e
执行以下命令,而不是执行保存在文件中的代码'
开始指令$_=~s
对整个文件执行替换($_
)/templateUrl:( \K.*))/
查找与正则表达式匹配的行templateUrl: .*
,并将与括号中的子表达式匹配的字符串捕获.*
到变量中($1
默认调用)templateUrl/
\K
将匹配行中标记后的部分替换为文本templateUrl
;
指令之间的分隔print"var templateUrl =$1\n"
打印var templateUrl =
,内容$1
和换行符- 此时,文件的其余部分将被隐式打印,因为
p
指定了开关 '
指令结束*
处理当前目录下的每个文件
当然可以有不同的方法,例如:
perl -i -ne 'if ($_=~s/templateUrl:( \K.*)/templateUrl/){$a="templateUrl =$1"} {$file.=$_} END{print"var $a\n$file"}' *
大王:
由于问题是关于sed
或awk
,值得注意的是,两种方法都可以同样轻松地实现awk
:
awk -i 'BEGIN {RS="\0"} {match($0,/templateUrl:( .*)/,m); gsub("templateUrl: .*","templateUrl: templateUrl"); print "var templateUrl ="m[1]$0}' *
awk -i '/templateUrl: / {a="templateUrl = "$2;gsub("templateUrl: .*","templateUrl: templateUrl")} NR==1 {file=$0} NR==2{file=file"\n"$0} END{print a"\n"file}' *