use*_*907 11 linux bash shell sh
我正在尝试编写一个bash脚本,它将执行以下操作:
例如:
first_file.txt:
111111
1111
11
1
Run Code Online (Sandbox Code Playgroud)
second_file.txt:
122221
2222
22
2
Run Code Online (Sandbox Code Playgroud)
图案:
2222
Run Code Online (Sandbox Code Playgroud)
输出:
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
Run Code Online (Sandbox Code Playgroud)
我应该用什么来实现BASH上的这个功能?
我编写了代码,但它无法正常工作(为什么?):
#!/bin/bash
first_filename="$1"
second_filename="$2"
pattern="$3"
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
Run Code Online (Sandbox Code Playgroud)
cho*_*oba 33
sed没有循环可以做到这一点.使用它的r命令:
sed -e '/pattern/rFILE1' FILE2
Run Code Online (Sandbox Code Playgroud)
测试环节:
$ 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
Run Code Online (Sandbox Code Playgroud)
使用awk也可以.
要在### 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
Run Code Online (Sandbox Code Playgroud)
要在### marker ###行之后插入:
// 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
Run Code Online (Sandbox Code Playgroud)
要替换### 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
Run Code Online (Sandbox Code Playgroud)
如果要进行就地替换,请使用临时文件以确保在awk读取整个文件之前管道未启动; 添加:
> second_file.txt.new
mv second_file.txt{.new,}
// (like "mv second_file.txt.new second_file.txt", but shorter to type !)
Run Code Online (Sandbox Code Playgroud)
如果你想在线内更换,(只替换模式并保留线的其余部分),应该用sed而不是awk实现类似的解决方案.
操作员周围需要有空间=~。比较:
[[ foo=~bar ]]\n[[ foo =~ bar ]]\nRun Code Online (Sandbox Code Playgroud)\n\n这是因为第一个表达式本质上计算为“此字符串是否为空?”
\n\n\n\n即便如此,您也可以轻松摆脱内循环。只需将整个while read -r line2位替换为cat -- "$second_filename".
echo $line仅当文件不以换行符结尾时(*nix 工具的标准),您的最后一个才是正确的。相反,您应该使用while read -r line || [[ $line ~= \'\' ]]. 无论末尾有或没有换行符,这都适用。