Bash:在模式之后将一个文件的内容插入到另一个文件中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16811173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash: Inserting one file's content into another file after the pattern
提问by user2431907
I'm trying to write a bash script, which will do the following:
我正在尝试编写一个 bash 脚本,它将执行以下操作:
- reads the content from the first file (as a first argument)
- reads the content from the second file (as a second argument)
- finds the line in the second file with the given pattern (as a third argument)
- inserts text from the first file to the second file after the line of the pattern.
- prints final file on the screen.
- 从第一个文件中读取内容(作为第一个参数)
- 从第二个文件中读取内容(作为第二个参数)
- 在第二个文件中找到给定模式的行(作为第三个参数)
- 将文本从第一个文件插入到模式行之后的第二个文件中。
- 在屏幕上打印最终文件。
For example:
例如:
first_file.txt:
first_file.txt:
111111
1111
11
1
second_file.txt:
第二个文件.txt:
122221
2222
22
2
pattern:
图案:
2222
output:
输出:
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
What should I use to realize this functionality on BASH?
我应该用什么来在 BASH 上实现这个功能?
I wrote the code, but it doesn't work properly (why?):
我写了代码,但它不能正常工作(为什么?):
#!/bin/bash
first_filename=""
second_filename=""
pattern=""
while read -r line
do
if [[ $line=?$pattern ]]; then
while read -r line2
do
echo $line2
done < $second_filename
fi
echo $line
done < $first_filename
采纳答案by l0b0
You need spaces around the =~operator. Compare:
您需要在=~运算符周围留出空间。相比:
[[ foo=~bar ]]
[[ foo =~ bar ]]
This is because the first expression essentially evaluates as "Is this string empty?"
这是因为第一个表达式基本上计算为“这个字符串是否为空?”
Also, the OP code uses small tilderather than tilde.
Even so, you can easily get rid of the inner loop. Just replace the whole while read -r line2bit with cat -- "$second_filename".
即便如此,您也可以轻松摆脱内部循环。只需将整个while read -r line2位替换为cat -- "$second_filename".
Your last echo $lineis only correct if the file does notend in a newline character (standard with *nix tools). Instead, you should use while read -r line || [[ $line ~= '' ]]. This works with or without newline at the end.
你最后echo $line是唯一正确的,如果该文件没有没有在一个换行符(与* nix的工具标准)结束。相反,您应该使用while read -r line || [[ $line ~= '' ]]. 这在最后有或没有换行符都有效。
Also, Use More Quotes?.
另外,使用更多引号?.
回答by choroba
sedcan do that without loops. Use its rcommand:
sed可以在没有循环的情况下做到这一点。使用它的r命令:
sed -e '/pattern/rFILE1' FILE2
Test session:
测试环节:
$ 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
回答by Pierre-Olivier Vares
Using awkworks as well.
使用awk也可以。
To insert before the ###marker### line :
在###marker### 行之前插入:
// for each <line> of second_file.txt :
// if <line> matches regexp ###marker###, outputs first_file.txt.
// **without any condition :** print <line>
awk '/###marker###/ { system ( "cat first_file.txt" ) } \
{ print; } \' second_file.txt
To insert after the ###marker###line :
在 ###marker###line 之后插入:
// 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
To replace the ###marker### line :
替换 ###marker### 行:
// 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
If you want to do in-place replacement, use a temp file for being sure the pipe doesn't start before awk has read the entire file; add :
如果要进行就地替换,请使用临时文件以确保管道在 awk 读取整个文件之前不会启动;添加 :
> second_file.txt.new
mv second_file.txt{.new,}
// (like "mv second_file.txt.new second_file.txt", but shorter to type !)
If you want replacement inside of the line, (replacing just the pattern and keeping the rest of the line), a similar solution should be achievable with sedinstead of awk.
如果您想在行内进行替换(仅替换模式并保留行的其余部分),则应该可以使用sed而不是awk来实现类似的解决方案。
回答by Julio Leiva
I use sed like this and it worked as a charm
我像这样使用 sed,它很有魅力
sed -i -e '/pattern/r filetoinsert' filetobeinserted
sed -i -e '/pattern/r filetoinsert' filetobeinsert
What it does is insert the 'filetoinsert' into 'filetobeinserted' after the line with the specified pattern
它的作用是在具有指定模式的行之后将 'filetoinsert' 插入到 'filetobeinsert' 中
Take care to choose a unique pattern, not sure how it will work with a duplicate patterns, I assume it will do it just of the first one
小心选择一个独特的模式,不确定它如何与重复的模式一起工作,我认为它只会做第一个
回答by Vijay
This should work:
这应该有效:
perl -lne 'BEGIN{open(A,"first_file.txt");@f=<A>;}print;if(/2222/){print @f}' second_file.txt
Tested:
测试:
> 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
>

