如何使用#include语句显示整个文件

如何使用#include语句显示整个文件

假设我有文件 main.txt,其中包含以下内容:


一些文字

#包含片段1.txt

其他一些文字

#包括fragment2.txt”

其他一些文字


其中fragment1.txt 和fragment2.txt 如下所示:

片段1.txt:


这是fragment1的内容


片段2.txt:


这是fragment2的内容


问题:如何显示带有“扩展”包含文件的整个 main.txt 文件,如下所示:


一些文字

这是fragment1的内容

其他一些文字

这是fragment2的内容

其他一些文字


谢谢

答案1

如果您要使用#include "file"C 编程语言中的语法,您可以使用cpp它来解析它。比如说,如果你main.txt 看起来像这样:

Some text

#include "fragment1.txt"

Some other text

#include "fragment2.txt"

Some other text

你可以这样做:

$ cpp -nostdinc -P <main.txt
Some text
This is content of fragment1
Some other text
This is content of fragment2
Some other text

正如中所解释的man cpp

-nostdinc 不要在标准系统目录中搜索头文件。仅搜索使用 -I 选项指定的目录(以及当前文件的目录,如果适用)。

-P 禁止在预处理器的输出中生成行标记。当在非 C 代码上运行预处理器时,这可能很有用,并且将被发送到可能被行标记混淆的程序。

但请注意,这cpp不仅仅是解析#include行,并且根据您的用例,它可能有用也可能没用。例如,cpp自动删除所有 C 风格注释:

// this is a comment
/* this as a comment too /*

它看起来很有用,如果您想保留评论,可以使用-C选项。另一件事是,它将cpp尝试解释所有以#预处理器指令开头的行。例如这个:

#define A 7
Value: A

将打印为:

Value: 7

和这个

#blah blah

会抛出错误:

<stdin>:14:2: error: invalid preprocessing directive #blah

在实践中,有一些程序依赖cpp作为其配置解析器,例如xrdb.

答案2

一个小脚本就可以解决字面量#include
不能递归,包含文件本身会造成死循环
并且递归包含没有按要求说明。

最终可能需要一个真正的解析器,你可以参考其他答案。

通过标准输入输入main.txt以下 perl 脚本,
输出是(大致)所需的输出。
awk 也可以完成这项工作,但我喜欢 Perl 的神秘感:)

#!/usr/bin/perl
while (<>) {
  if (/^#include (.*)/) {
    system('cat',$1);
  } else {
    print;
  }
}

上述代码的更短的单行版本:

perl -e '(/^#include (.*)/ ? system("cat",$1) : print) while <>;' <main.txt

对于那些可能有兴趣了解更多 Perl 的人:

  • <>是 read from 的缩写STDIN,它是标准输入流

  • 关键字while可以放在行尾;()当没有歧义的解释时可以省略。

  • 对于从 读取的每一行STDIN,perl 将其存储在$_

  • $_是一个预定义变量,大多数 perl 内置函数在未给出参数的情况下接受该变量作为参数,

  • print是接受的内置函数之一$_

  • 读取每一行后,perl 将计算三元表达式。正则表达式匹配$_默认适用

  • /^#include (.*)/ 返回1(检测到的匹配数)时,表示$_以文字开始#include

  • $_perl 存储to的剩余部分$1,因为它是第一个分组捕获($2,$3...如果有更多组则定义)

  • system函数通过系统 shell 调用命令,主要是sh
    在这一行中调用cat,并$1作为其参数传递。

  • 当 ,/^#include (.*)/上返回 0时$_print会被评估并作为副作用,它会打印出来$_

  • 三元表达式的值被默默忽略

答案3

直接运行C预处理器:

$ cpp -P main.txt

这样就可以了。不过,您需要引用包含文件的名称:

#include“fragment1.txt”

作为奖励,您可以获得 C 预处理器的全部功能:宏、条件包含等。

答案4

使用 GNU sed,您可以在命令中使用该e标志s

sed 's/^#include/cat/e'

替换#includecat并执行它,因此该行被命令的答案替换cat

如果文件名可能包含空格等字符,最好引用它:

sed 's/^#include *\(.*\)/cat "\1"/e'

但请注意,对于带有反斜杠、勾号和其他一些特殊文件名,这仍然可能会失败。

相关内容