递归多行替换:更改版权标题

时间:2014-02-11 10:50:01

标签: replace sed awk

我正在尝试用新版本替换项目中的所有版权标题(100多个文件)。目前我在每个文件的开头有这样的东西:

<?php
/**
 * Project name
 *
 * @copyright Apache 2.0
 * @author    FooBar
 */

我希望我的所有文件都像这样开始:

<?php
/**
 * Copyright 2014 FooBar
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

我已经看过了:

  • this thread,我无法工作。它会进行部分替换,在新文本中保留原始文本的某些行。我想要一个完整的替代品。

  • this script,同样对我的用例不起作用。它使用新标头替换每个文件的开头,这会导致现有内容(<?php /** */)附加到新注释,从而导致解析错误。

有人知道我怎么能做一个递归的多行文件替换吗?我需要使用sed / awk吗?

SOLUTION:

我只需要执行这个bash脚本:

INPUT=../path

find $INPUT -name "*.php" -exec sed -i -e '2,/\*\//d; 1r copyright.txt' {} \;

4 个答案:

答案 0 :(得分:4)

假设所有文件都以

开头是否安全
<?php
/**

如果是,您可以使用

sed '2,/\*\//d; 1r newSig.txt' input.txt

第一个命令从第2行删除签名,直到签名结束。您可以使用动态范围,但也会删除文件中的其他多行签名。第二个命令读取具有新签名的文件newSig.txt,并在第1行后附加。

答案 1 :(得分:3)

使用GNU awk进行多字符RS将整个文件作为单个字符串读取:

$ gawk -v RS='^$' -v hdr="\
/**
 * Copyright 2014 FooBar
 *
 * Licensed under the blah blah blah
 */\
" '{sub(/\/\*[^/]+\*\//,hdr)}1' file
<?php
/**
 * Copyright 2014 FooBar
 *
 * Licensed under the blah blah blah
 */

答案 2 :(得分:2)

注意 :您也应该阅读Ed Morton's comment。关于这是一个问题,您可以在运行awk脚本之前检查文件并仅传递您可读的文件以进行循环。

如果您的文件始终如此开始,使用gawk解决问题的一种方法是

awk 'FNR==1 { print $0
              print "INSERT YOUR new header here even on multiline print statements." 
              # if you don't mind your old header, stop here and skip the below rules
            }
     FNR==2 && $0 ~ "/\*\*" { 
              while (getline) {
                if ($0 == "*/") { getline ; break }
              }
            }
     FNR>2  { print $0 }' INPUTFILE

你可以把它包裹在for周期中,比如

for file in *php ; do
    awk ... $file > $file.new
done

答案 3 :(得分:1)

我的方式对

的修复行没有限制
<?php
/**

它会将第一对/**替换为下一个**/

1)将替换内容保存到文件中:update.txt(未设置后缀为php)

2)然后在一个php文件(abc.php)上运行此命令以确认第一个

sed ':a;$!{N;ba};s!/[^/]*/!########!1' abc.php|sed -e '/########/{r update.txt' -e 'd}'

3)如果没问题,那么在所有php文件上运行脚本:

for file in *.php
do
  sed ':a;$!{N;ba};s!/[^/]*/!########!1' $file|sed -e '/########/{r update.txt' -e 'd}' > temp
  mv temp "$file"
done