Shell 如何使用sed替换文件中多次出现的变量?
我已经在编写一个脚本来替换shell脚本中Makefile中变量“SUBDIRS”的值。 我使用了下面的命令,它工作正常,但在第一次出现“SUBDIRS”后退出,并且makefile不完整Shell 如何使用sed替换文件中多次出现的变量?,shell,sed,makefile,Shell,Sed,Makefile,我已经在编写一个脚本来替换shell脚本中Makefile中变量“SUBDIRS”的值。 我使用了下面的命令,它工作正常,但在第一次出现“SUBDIRS”后退出,并且makefile不完整 sed -z -i "s/\(SUBDIRS = \).*/\1$(tr '\n' ' ' < changed_fe_modules.log)\n/g" Makefile sed-z-i“s/\(SUBDIRS=\)./\1$(tr'\n''”
sed -z -i "s/\(SUBDIRS = \).*/\1$(tr '\n' ' ' < changed_fe_modules.log)\n/g" Makefile
sed-z-i“s/\(SUBDIRS=\)./\1$(tr'\n''”
现在我想保持Makefile的原样,只替换3次出现的“SUBDIRS=abcdefgh”并正确更新Makefile
请建议如何替换所有3个引用,并将Makefile端到端保留为原始文件
Makefile输入示例:
Makefile所需的输出示例:
现在,当前命令给了我以下输出:它在第一次替换后退出,文件不完整
sed -z -i "s/\(SUBDIRS = \).*/\1$(tr '\n' ' ' < changed_fe_modules.log)\n/g" Makefile
这将非常困难 您看到这种行为的原因是您正在对sed使用
-z
选项。-z
选项使用NUL字符分隔行,而不是换行符。这意味着为了sed的模式匹配,整个文件(直到第一个NUL字符,这里没有)被视为一条“线”
所以这个正则表达式:
\(SUBDIRS = \).*
此处的*
匹配第一个子项=
匹配后的整个文件其余部分。然后用changed\u fe\u modules.log
文件的内容替换文件的其余部分。在那之后,没有什么可以匹配的了,所以sed就完成了
如果您的原始makefile在一行上列出了所有子曲面,而不使用反斜杠/换行分隔符,那么这将很简单;您只需使用:
sed -i "s/^SUBDIRS = .*/SUBDIRS = $(tr '\n' ' ' < changed_fe_modules.log)/" Makefile
sed-i“s/^SUBDIRS=.*/SUBDIRS=$(tr'\n'
如果必须使用反斜杠/换行符,则可能无法使用sed进行此更改。您需要使用更强大的工具,如Perl,它具有非贪婪匹配功能
埃塔
您也可以在纯shell中编写:
new_subdirs=$(tr '\n' ' ' < changed_fe_modules.log)
line_cont=false
in_subdirs=false
while read -r line; do
if $line_cont; then
case $line in
(*\\) : still continuing ;;
(*) line_cont=false ;;
esac
$in_subdirs || printf '%s\n' "$line"
continue
fi
case $line in
(SUBDIRS =*)
echo "SUBDIRS = $new_subdirs"
in_subdirs=true ;;
(*) printf '%s\n' "$line"
in_subdirs=false ;;
esac
case $line in
(*\\) line_cont=true ;;
esac
done < Makefile > Makefile.new
mv -f Makefile.new Makefile
new\u subdirs=$(tr'\n'Makefile.new
mv-f Makefile.new Makefile
(注意,完全未经测试)给出
Makefile
的示例数据和您的预期输出。@Utsav更新了我的问题,提供了更多详细信息。为什么要以重复多次相同的SUBDIRS语句结束?在awk中,您尝试执行的任何操作都是微不足道的,但您必须添加简洁、可测试的示例输入和预期输出(即文本,而不是文本的照片!),并添加awk标记以获得帮助。感谢您的解释。这就更清楚了。我将看看我是否可以在这里使用任何其他语言,因为我的脚本的其余部分是在bash中。