我想问一下如何在保留标签的同时用文件内容替换文件中的字符串。例如:
要转换的文件:
first line
second line
string_to_substitute
forth line
fifth line
包含内容的文件:
{
"string1":"test",
"string2":"test2"
}
我希望实现的结果(用文件内容替换string_to_substitute
):
first line
second line
{
"string1":"test",
"string2":"test2"
}
forth line
fifth line
我尝试了sed
和perl
替换,但只取得了类似的结果:
first line
second line
{
"string1":"test",
"string2":"test2"
}
forth line
fifth line
或
first line
second line
{
"string1":"test",
"string2":"test2"
}
forth line
fifth line
答案 0 :(得分:1)
这个单一的awk命令可以处理这个:
awk 'FNR==NR{
a = a (a=="" ? "":RS) $0
next
}
/string_to_substitute/ {
sub(/[^[:blank:]].*$/, "")
gsub(/\n/, "\n" $0, a)
$0 = $0 a
} 1' content.txt file.txt
first line
second line
{
"string1":"test",
"string2":"test2"
}
forth line
fifth line
答案 1 :(得分:0)
这是一个awk解决方案:
$ awk -v f=content '/string_to_substitute/{sub(/[^\t].*/, ""); while (getline new<f) print $0 new; close(f); next} 1' file1
first line
second line
{
"string1":"test",
"string2":"test2"
}
forth line
fifth line
因为这种方法不需要将任何文件读入内存,所以即使对于大文件也应如此。
-v f=content
这会将带有新内容的文件名称分配给awk变量f
。
/string_to_substitute/{...}
当我们到达与正则表达式string_to_substitute
匹配的行时,我们执行花括号中的命令。我们将在下面讨论以下每个命令:
sub(/[^\t].*/, "")
这将从当前行$0
中删除从非制表符到行尾的所有内容。换句话说,这只保留当前行的缩进标签。
while (getline new<f) print $0 new
循环遍历文件f
并打印每行所需的缩进。
close(f)
这会关闭文件f
。
next
这告诉awk跳过剩余的命令并跳转到next
行。
1
我们到达此处,我们不在string_to_substitute
行。
1
是用于打印线的awk简洁速记。
对于那些发现如果命令分布在多行上更容易理解的人:
awk -v f=content '
/string_to_substitute/{
sub(/[^\t].*/, "")
while (getline new<f)
print $0 new
close(f)
next
}
1
' file1
答案 2 :(得分:0)
Perl救援:
#!/usr/bin/perl
use warnings;
use strict;
my ($content_filename, $to_transform_filename) = @ARGV;
my @content_lines = do {
open my $CONTENT, '<', $content_filename or die $!;
<$CONTENT>;
};
open my $TO_TRANSFORM, '<', $to_transform_filename or die $!;
while (<$TO_TRANSFORM>) {
if (my ($prefix) = /^(\s*)string_to_substitute$/) {
print "$prefix$_" for @content_lines;
} else {
print;
}
}
另存为transform
,以perl transform -- content-file file-to-transfer
运行。
它首先读取&#34;内容&#34;的内容。将文件存入@content_lines数组。
然后,它逐行读取另一个文件,当该行包含要替换的字符串时,它会记住它之前的空白\s*
并将其预先添加到数组中的每一行。打印不匹配的行没有任何变化。
答案 3 :(得分:0)
Pure bash解决方案 - 将内容文件作为参数
contentf=$1
pat="^(\s*)string_to_substitute"
while IFS= read -r line; do
unset IFS
if [[ ! $line =~ $pat ]]; then
echo "$line"
continue
fi
pfx=${BASH_REMATCH[1]}
# can use sed instead of inner while read loop
# sed "s/^/$pfx/" $contentf
while IFS= read -r contentline; do
unset IFS
echo "$pfx$contentline"
done <$contentf
done