Linux Bash:插入一个文件&x27;将内容插入模式后的另一个文件中
我正在尝试编写一个bash脚本,它将执行以下操作:Linux Bash:插入一个文件&x27;将内容插入模式后的另一个文件中,linux,bash,shell,sh,Linux,Bash,Shell,Sh,我正在尝试编写一个bash脚本,它将执行以下操作: 从第一个文件读取内容(作为第一个参数) 从第二个文件读取内容(作为第二个参数) 在第二个文件中查找具有给定模式的行(作为第三个参数) 将文本从第一个文件插入到图案行后的第二个文件中 在屏幕上打印最终文件 例如: 第一个文件.txt: 111111 1111 11 1 122221 2222 22 2 第二个_file.txt: 111111 1111 11 1 122221 2222 22 2 模式: 2222 输出: 122221
111111
1111
11
1
122221
2222
22
2
第二个_file.txt:
111111
1111
11
1
122221
2222
22
2
模式:
2222
输出:
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
我应该用什么在BASH上实现这个功能
我写了代码,但它不能正常工作(为什么?)
#/bin/bash
第一个文件名=“$1”
第二个文件名=“$2”
pattern=“$3”
而read-r行
做
如果[[$line=]$$pattern]];然后
当读取-r行2时
做
echo$line2
完成<$second\u文件名
fi
回音$线
完成<$first\u文件名
sed
可以在没有循环的情况下完成。使用其r
命令:
sed -e '/pattern/rFILE1' FILE2
测试会话:
$ cd -- "$(mktemp -d)"
$ printf '%s\n' 'nuts' 'bolts' > first_file.txt
$ printf '%s\n' 'foo' 'bar' 'baz' > second_file.txt
$ sed -e '/bar/r./first_file.txt' second_file.txt
foo
bar
nuts
bolts
baz
在
=~
运算符周围需要空格。比较:
[[ foo=~bar ]]
[[ foo =~ bar ]]
这是因为第一个表达式的计算结果本质上是“ThisString为空吗?”
此外,操作代码使用而不是
即使如此,您也可以轻松摆脱内部循环。只需将整个while read-r line2
位替换为cat--“$second\u filename”
只有当文件未以换行符结尾时,您的最后一个echo$line
才是正确的(标准的*nix工具)。相反,您应该在读取-r行| |[[$line~='']]时使用。这适用于末尾有或没有换行符的情况
此外,.这应该可以:
perl -lne 'BEGIN{open(A,"first_file.txt");@f=<A>;}print;if(/2222/){print @f}' second_file.txt
perl-lne'开始{open(A,“first_file.txt”);@f=}打印;如果(/2222/){print@f}'second_file.txt
测试:
> cat temp
111111
1111
11
1
> cat temp2
122221
2222
22
2
> perl -lne 'BEGIN{open(A,"temp");@f=<A>;}print;if(/2222/){print @f}' temp2
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
>
>cat温度
111111
1111
11
1.
>cat temp2
122221
2222
22
2.
>perl-lne'BEGIN{open(A,“temp”);@f=;}print;如果(/2222/){print@f}'temp2
122221
111111
1111
11
1.
2222
111111
1111
11
1.
22
2.
>
使用awk
也可以
要在#####标记###行之前插入,请执行以下操作:
如果您希望在生产线内部进行更换(仅更换模式并保留生产线的其余部分),则可以使用sed而不是awk,实现类似的解决方案。我这样使用sed,它很有魅力 sed-i-e'/pattern/r filetoinsert'filetobeinserted 它所做的是在具有指定模式的行后面的“filetoinsert”中插入“filetobeinserted”
注意选择一个独特的模式,不确定它将如何与重复的模式一起工作,我假设它只会在第一个模式中这样做对于第四个点,
sed-I“line,text…”
可以做到。你能举个小例子吗?(输入和预期输出)当前代码中发生了什么?“不起作用”不是一个很好的错误description@EmilVikstrom:我的代码只是在第二个文件名的每一行中输出第一个文件名的内容。不正确../replace_shell.sh:第9行:应为条件二进制运算符。/replace_shell.sh:第9行:=$]附近的语法错误。/replace_shell.sh:第9行:
如果[[$line=$$pattern]];然后,当我尝试这样做:“cat--“$second_filename”:我得到了一个错误:sed:1:“file2.txt”“:无效的命令代码f@user2431907=$
与=~
不同<代码>是。@user2431907sed
?原始代码中没有sed
命令。如果需要帮助,最好发布实际代码。+1从未听说过r
命令。添加了一个要验证的测试会话。是否有办法确保它只插入一次?@l0b0sed-e'1,/pattern/rFILE1'FILE2
将只插入一次,但在第一行出现了一个边缘情况。在这种情况下,使用GNU sed:sed'0,/pattern/rFILE1'FILE2
@l0b0@potong:Or,使用分支:sed-e'/pattern/{r FILE1'-e'br'-e'-e'-b'-e':r{n;br'-e'-e'-2
对于“只做一次”请求,有时ed
,虽然比sed更详细,但比sed:printf s\n'/2222/r first\r'-txt文件1更清晰,$p'q | ed second_file.txt 2>/dev/null
--若要就地编辑,请将'1,$p'替换为'w'这是一种处理方式,当变量中有引号时,sed无法真正处理我的awk解决方案(替换标记):awk-v f=“$file”/#marker#marker##/{system(“cat”f);next};1'--其中要插入的文件$file的名称中不能有空格:/
// for each <line> of second_file.txt :
// **without any condition :** print <line>
// if <line> matches regexp ###marker###, outputs first_file.txt.
awk '{ print; } \
/###marker###/ { system ( "cat first_file.txt" ) } \' second_file.txt
// for each <line> of second_file.txt :
// if <line> matches regexp ###marker###, outputs first_file.txt.
// **else**, print <line>
awk '/###marker###/ { system ( "cat first_file.txt" ) } \
!/###marker###/ { print; }' second_file.txt
> second_file.txt.new
mv second_file.txt{.new,}
// (like "mv second_file.txt.new second_file.txt", but shorter to type !)