14

我正在尝试编写一个 bash 脚本,它将执行以下操作:

  1. 从第一个文件中读取内容(作为第一个参数)
  2. 从第二个文件中读取内容(作为第二个参数)
  3. 在第二个文件中找到具有给定模式的行(作为第三个参数)
  4. 在模式行之后将文本从第一个文件插入到第二个文件。
  5. 在屏幕上打印最终文件。

例如:

first_file.txt:

111111
1111
11
1

second_file.txt:

122221
2222
22
2

图案:

2222

输出:

122221
111111
1111
11
1
2222
111111
1111
11
1
22
2

我应该用什么来在 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
4

5 回答 5

37

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
于 2013-05-29T10:23:57.723 回答
10

使用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

在 ###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

要替换 ###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

如果要进行就地替换,请使用临时文件以确保在 awk 读取整个文件之前管道不会启动;添加 :

> second_file.txt.new
mv second_file.txt{.new,}
// (like "mv second_file.txt.new second_file.txt", but shorter to type !)

如果您想在行内进行替换(仅替换模式并保留行的其余部分),使用sed而不是awk应该可以实现类似的解决方案。

于 2013-12-18T11:20:14.620 回答
4

我像这样使用 sed,它起到了一种魅力

sed -i -e '/pattern/r filetoinsert' 待插入的文件

它的作用是在具有指定模式的行之后将“filetoinsert”插入“filetobeinserted”

小心选择一个独特的模式,不确定它如何与重复的模式一起工作,我认为它只会做第一个模式

于 2017-10-25T18:46:51.117 回答
2
于 2013-05-29T10:43:10.587 回答
1

这应该有效:

perl -lne 'BEGIN{open(A,"first_file.txt");@f=<A>;}print;if(/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
> 
于 2013-05-29T11:04:43.580 回答