我有一个文件,其中包含尖括号中的相对路径,如下所示(example.txt):
Some content containing <../another.txt> file
然后在父目录中,文件another.txt:
another
我可以使用什么 Linux 命令行来生成example_processed.txt,将<path>
令牌替换为指定路径处文件的内容?例如,我想要一个命令来提取example.txt并生成包含以下内容的example_processed.txt :
Some content containing another file
请注意,我不关心生成的文件中是否有无关的换行符,因此以下输出也是可以接受的(这只是一个示例,任何无关的空格都是可以接受的):
Some content containing
another
file
我有一个 bash 循环,可以将文件的内容读入变量,但同样,不知道这是否有助于我执行替换:
cp example.txt example_processed.txt
grep -oP '<\K.*(?=>)' example.txt | while read -r REPL_PATH ; do
local CONTENTS=$(<"$REPL_PATH")
# TODO: How do I use this? The following is what I want to work:
# sed "s/<$REPL_PATH>/$CONTENTS/g"
echo "$REPL_PATH: $CONTENTS"
done
这是产生最接近的结果,但要求another.txt位于同一目录中:
sed -e '/<\(.*\)>/{' -e 's/<.*>//' -e 'r another.txt' -e '}' -i example.txt
以上输出:
Some content containing file
another
问题:
- 如何将替换路径指定为../another.txt?
- 如何将上述命令中的文字another.txt替换为捕获组 #1 的结果?例如,
sed -e '/<\(.*\)>/{' -e 's/<.*>//' -e 'r \1' -e '}' -i example.txt
- 如何将替换字符串移动到“包含”和“文件”之间,而不是“文件”之后?
我的想法是将输入文件转换为以下形式的 shell 脚本:
其中
…
是输入文件的原始内容,但被<pathname>
替换$(cat pathname)
,因此当脚本由 shell 解释时,它是一个命令替换,将被 的输出替换cat pathname
。这是命令:
一步步:
<example.txt sed
–sed
阅读example.txt
并执行以下操作:s/[$\\`]/\&/g
– 转义每个$
,\
和`
,否则它们在我们的此处文档中会很特殊;s/<\([^<>]*\)>/$(\n$$\1\n)/g
– 将和之间的每个字符串(不包含<
or>
,所以非贪婪地)转换为<
>
1 i cat <<EOF$
cat <<EOF$
–在第一行之前插入;$ a EOF$
– 添加EOF$
到最后一行之后。| sed
– 第二个sed
从第一个读取并且/^\$\$/
– 标识以以下开头的行$$
(注意它们必须来自第一行,因为原始文件中的sed
每个行现在前面都有一个反斜杠),并且有:$
s/[^$\\`]/\&/g
$
– 除,\
或之外的每个字符`
均通过反斜杠转义(排除的字符已在适当的情况下转义)s/^\$\$/cat -- /
– 并且领先$$
被替换cat --
。| sh >example_processed.txt
– POSIX shell 解释生成的脚本并写入example_processed.txt
您的示例文件将变为
sh
以下脚本:笔记:
EOF$
使用而不是传统的EOF
,因此原始文件中的任何内容都不会干扰。即使EOF$
原始文件中有,在脚本中也将是EOF\$
.<
并且相应的>
换行符必须位于同一输入行中,我们的代码才能工作。../another.txt
脚本中的路径名(在示例中)是完全转义的(逐个字符),因此即使您使用带有空格、星号或其他内容的路径名,它也是安全的。$(…)
去掉尾随换行符,这通常没问题。--
此处解释:(双破折号)是什么意思?--
<…>
将根据 的工作目录进行解析sh
,而不是针对包含输入文件的目录。在我们的示例中,它是相同的目录,但通常这些目录可能不同。如果您想解析相对于输入文件目录的相对路径,那么您必须sh
在这个确切的目录中运行,就像我们所做的那样。最终结果为
example_processed.txt
: