根据文件中的其他行,在文件开头添加一行

根据文件中的其他行,在文件开头添加一行

我有以下结构的文件:

foo.bar.baz () ->
  templateUrl: require('x.jade')

我需要转换这些文件以便:

  1. 它们的前缀是var templateUrl = require('x.jade')
  2. templateUrl:行被替换为templateUrl: templateUrl

我该怎么做?一个选项是针对每个文件使用 bash 脚本:

  1. greptemplateUrl:获得该require部件。
  2. cat将该var templateUrl行和文件一起合并为一个新文件,然后替换原文件。
  3. 用来sed代替。templateUrl: require...templateUrl

但是,可以通过针对每个文件执行的单个脚本sed来实现这一点吗?awk

答案1

@simlev 的perl解决方案确实步骤较少,但我想介绍一下我的sed命令。这更有意义,因为 OP 已经设想使用sed并明确要求使用sedawk脚本。

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"}' *

大王
由于问题是关于sedawk,值得注意的是,两种方法都可以同样轻松地实现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}' *

相关内容