因此,我尝试从包含其他文件的源文件创建输出文件。
(我的用例实际上是 Kubernetes/OpenShift 的 YAML,但这些 .txt 文件显示了目标。)
例如:
% cat source.txt
This is the source files it will include two other files.
The first will be here:
#INCLUDE ./first-included-file.txt
And the second file will be inserted here:
#INCLUDE ./second-included-file.txt
And this is the end of source.txt
如果包含的文件是:
% cat first-included-file.txt
This is FIRST
End of FIRST
% cat second-included-file.txt
This is SECOND
End of SECOND
那么输出将是:
This is the source files it will include two other files.
The first will be here:
This is FIRST
End of FIRST
And the second file will be inserted here:
This is SECOND
End of SECOND
And this is the end of source.txt
其他答案使用
sed '/#INCLUDE/ r insertfile'
但是是否有一个通用的解决方案可以从源中的值找到文件名?
我猜想读取并解析每一行的 Bash 脚本可能会完成这项工作,但是也许awk
或者其他东西可以做到这一点?
答案1
程序文件- 可以使用C 预处理器命令。该命令通常包含在大多数 Linux 发行版的gcc
或软件包中。cpp
虽然它被称为 C 预处理器,但它也可以用于其他文件,并且您可以使用标准 C 预处理器指令,例如#include
、#define
等#ifdef
。
例如:
源文件.txt
This is the source files it will include two other files.
The first will be here:
#include "first-included-file.txt"
And the second file will be inserted here:
#include "second-included-file.txt"
And this is the end of source.txt
第一个包含文件.txt
This is FIRST
End of FIRST
第二个包含文件.txt
This is SECOND
End of SECOND
的输出cpp -P source.txt
$ cpp -P source.txt
This is the source files it will include two other files.
The first will be here:
This is FIRST
End of FIRST
And the second file will be inserted here:
This is SECOND
End of SECOND
And this is the end of source.txt
笔记:
- 该
-P
标志禁止在预处理器的输出中生成行标记。 - 手册页
- 关于“您可以使用标准 C 预处理器指令,例如 #include、#define、#ifdef 等”。 - 但如果您不希望这样,而只想按原样包含文件,那么除了将每个 #INCLUDE 转换为 #include 并将包含的文件名用引号引起来之外,您还必须执行某些操作来禁用字符串的任何出现 # include、#define、#ifdef 等可能恰好在运行 cpp 之前出现在您的输入中,否则它会根据出现的这些字符串对您的文本进行不必要的转换。
- 如果本地目录中缺少要包含的文件(假设您的 cpp 实现确实首先搜索本地目录,通常是这种情况),您也可能会得到意外结果,但 cpp 可以在以下目录之一中找到同名文件:它搜索包含文件的其他实现定义的目录。
答案2
调整“d)输入文件的递归下降解析,例如:”http://awk.freeshell.org/AllAboutGetline#INCLUDE
即使 include
您的文件名包含非换行符空格,您也可以使用任何 awk 执行以下操作:
awk '
function read(file) {
while ( (getline < file) > 0) {
if ( sub(/^#INCLUDE[ \t]+/,"") ) {
read($0)
} else {
print
}
}
close(file)
}
BEGIN {
read(ARGV[1])
}
' source.txt
This is the source files it will include two other files.
The first will be here:
This is FIRST
End of FIRST
And the second file will be inserted here:
This is SECOND
End of SECOND
And this is the end of source.txt
上面假设您没有递归包含 - 如果您这样做,则添加实现您想要的递归含义所需的任何逻辑。
答案3
使用乐(以前称为 Perl_6)
heredocs
Perl 和 Raku 都有一个称为(即引用“doc here”)的引用结构:to
,它可以提供所需的输出:
源文件.txt
my $file1 = '/path/to/first-included-file.txt'.IO.lines.join("\n");
my $file2 = '/path/to/second-included-file.txt'.IO.lines.join("\n");
my $pre-processed = qs:to/TERMINATOR/;
This is the source files it will include two other files.
The first will be here:
$file1
And the second file will be inserted here:
$file2
And this is the end of source.txt
TERMINATOR
put $pre-processed;
第一个包含文件.txt
This is FIRST
End of FIRST
第二个包含文件.txt
This is SECOND
End of SECOND
的输出raku source.txt
This is the source files it will include two other files.
The first will be here:
This is FIRST
End of FIRST
And the second file will be inserted here:
This is SECOND
End of SECOND
And this is the end of source.txt
您无需学习整个 Raku 语言即可仅使用这种引用语言,在 Raku 行话中称为“Q-lang”(或俚语)。上面,使用代码调用了最小插值qs:to/TERMINATOR/;
。在这里,qs
告诉 Raku 仅插入“标量”或$
-sigiled 变量(使用qq
它会插入所有 Raku 变量)。其他(中间)插值选项可以在下面找到。
https://docs.raku.org/syntax/heredocs%20%3Ato
https://docs.raku.org/language/quoting
https://stackoverflow.com/a/76624379/7270649
https://raku.org
答案4
“m4”宏(名称以“m”开头,后面有 4 个字母)程序将执行包含操作。然而,包含的形式是:“include (`file')”。请参阅“信息 m4”。