10

我需要用 Apache License 2.0 头文件替换我所有 Java 源文件中的 LGPL 许可证头文件,即这个

/*
 * Copyright (c) 2012 Tyler Treat
 * 
 * This file is part of Project Foo.
 *
 * Project Foo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Project Foo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Project Foo.  If not, see <http://www.gnu.org/licenses/>.
 */

需要成为

/*
 * Copyright (c) 2012 Tyler Treat
 * 
 * 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.
 */

我认为最简单的方法是使用 sed 对所有出现的此版权标头进行查找和替换。我有点像 Unix 新手,所以我在让命令按我需要的方式工作时遇到了问题——特别是在处理多行字符串时。基本上,类似于下面的内容,除了代替fooand的相应标题bar

find . -name "*.java" -print | xargs sed -i 's/foo/bar/g'

我知道 sed 一次只能在一条线上工作,所以也许有更好的解决方案?

4

3 回答 3

14
find . -name "*.java" -print0 | xargs -0 \
sed -i -e '/Project Foo is free software/,/along with Project Foo/c\
 * 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.'

c命令将行范围更改为指定的文本。该范围由包含“Project Foo is free software”的行到包含“aong with Project Foo”的行标识。表示 GNU的-i选项;因此,我假设您也有 GNU ,并且使用并避免文件名中出现空格等问题。sedsedfindxargs-print0-0

为此,我可能很想将sed脚本放入文件 ( sed.script) 中,然后可以将其用于:

find . -name "*.java" -exec sed -i -f sed.script {} +

我认为这更整洁,但美丽在旁观者的眼中。


只有一个问题:星号上的对齐有点偏离,我需要使用某种空白字符来缩进它们吗?我尝试在替换字符串中添加空格,但这似乎没有效果。

Grrr ......这是我可以做到的那种恼怒(你也是)。似乎“更改”数据行上的前导空格被删除了sed。似乎是sed而不是bash;我ksh使用脚本文件而不是-e命令行上的选项得到了相同的结果。您不能在输出时编辑“更改”数据。

一个可行的技巧——但你可能不喜欢它:

$ cat sed.script
/Project Foo is free software/,/along with Project Foo/c\
 * 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.
$ s2p -f sed.script > perl.script
$ find . -name "*.java" -exec perl -f perl.script -i.bak {} +
$

s2p程序是 Perl 发行版的标准部分,它将sed脚本转换为 Perl 脚本,但它保留了替代数据中的前导空格。我对此并不热衷,但我能想到的唯一选择是通过每个文件两次。替换数据可能是:

$ cat sed.script
/Project Foo is free software/,/along with Project Foo/c\
@*@ 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.
$

完成主要文本替换后,您将执行以下操作:

$ find . -name "*.java" -exec sed -i 's/^@\*@/ */' {} +
$

这将跟踪开始的行@*@并将该文本替换为“ *”(空白星号)。不那么整洁,但我相信你不会经常这样做。

于 2013-01-01T02:11:08.783 回答
6

使用 GNU Sed 替换部分许可证

您可以使用 GNU sed 通过一些正则表达式行匹配和读取表达式来解决此问题。以下是步骤。

使用文件保存替换文本

首先,创建一个文件来保存许可证的替换部分:

cat << EOF > /tmp/license
 * 
 * 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.
 */
EOF

运行实际的 Sed 调用

接下来,运行find收集您的文件列表,并调用以下 sed 脚本进行更改:

find . -name '*.java' |
xargs sed -i'' '/Copyright.*Tyler Treat/,/\*\// {
                    /Copyright/n
                    /\*\//r /tmp/license
                    d
                }'

兼容性说明

此解决方案可能适用于其他版本的 sed,也可能不适用,但已在本地测试并已知适用于 GNU sed 版本 4.2.1。如果它不适用于您的 OS X 版本附带的 sed 版本,您可以通过MacPorts或类似工具安装 GNU sed。

于 2013-01-01T02:11:11.497 回答
2

假设 file1 包含您的原始文本,而 file2 包含您的替换版权注释:

awk 'f; /\*\//{system("cat file2");f=1}' file1

以上只是在原始文件中查找第一个注释结尾行,当它找到替换文件并打开原始文件其余部分的打印时。

于 2013-01-01T17:36:05.183 回答