Contents

在指定模式后将多行插入文件

1. 概述

在处理文本文件时,我们可能需要在指定模式之后插入多行文本块。在本教程中,我们将了解一些可用于此目的的 Bash 实用程序。

2. 设置

首先,让我们设置我们将在大部分教程中使用的输入文件:

$ cat stocks.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

另外,让我们创建另一个文件,其中包含我们要插入到原始文件中的多行文本:

$ cat missing_data.csv
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85

现在,让我们看看在 匹配模式*“08-08-2021,SCRIP5,340”的行之后将内容从missing_data.csv文件插入到stocks.csv文件的各种解决方案。

3. 使用sed编辑器在文件中插入行

让我们从可用的最强大的文本操作工具之一,即*sed * 编辑器开始我们的探索。

3.1. 当数据在另一个文件中时

我们来看看如何将 missing_data.csv文件中的数据插入stocks.csv文件:

$ sed -i '/08-08-2021,SCRIP5,340/r missing_data.csv' stocks.csv
$ cat stocks_new.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

在这种情况下,我们在*/ 中指定了要匹配的模式。* ./ 块的sed命令。此外,我们使用r标志从missing_data.csv文件中读取数据

除此之外,我们还使用*-i*选项来修改我们的文件

3.2. 在sed命令中指定数据时

在上一节中,我们看到了如何从文件中插入数据。但是,我们也可以在sed命令本身中提供要添加的数据。让我们来看看:

$ sed -i "/08-08-2021,SCRIP5,340/a\08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85" stocks.csv
$ cat stocks_new.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

在这里,我们使用sed命令的** *“a”*标志指定要在匹配模式之后附加的行。**请注意,我们在输入数据中使用换行符 ( \n ) 来突出显示换行符。

3.3. 从stdin读取数据

在上一节中,我们看到了一种直接插入数据的方法,而无需先将其写入文件。但是,正如我们所见,它会使命令冗长且容易出错。或者,我们也可以*使用*heredoc 读取stdin

$ cat << EOF | sed -i '/08-08-2021,SCRIP5,340/r /dev/stdin' stocks.csv
> 08-08-2021,SCRIP6,49
> 08-08-2021,SCRIP7,76
> 08-08-2021,SCRIP8,85
> EOF
$ cat stocks_new.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

在这种情况下,我们的分隔符标记是EOF,我们使用cat命令来打印用户输入。随后,我们将此信息通过管道传递给sed命令。因此,/dev/stdin文件有效地包含通过管道传送到sed命令的数据。

4. 使用awk实用程序在文件中插入行

在本节中,我们将检查使用awk 实用程序在指定模式之后在文件中插入多行文本块的几种方法。

4.1. 在awk命令中指定数据时

让我们通过在awk命令中直接指定它们来检查插入行的方法:

$ awk '/08-08-2021,SCRIP5,340/{print $0 "\n08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85";next}1'
stocks.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

输出符合我们的预期。此外,让我们将这个命令分成几部分来讨论它是如何工作的。

我们可以在 / 中的awk命令中指定匹配模式。 .*/ 块。在我们的例子中,“/08-08-2021,SCRIP5,340/”成为匹配模式。我们**使用“print $0”语法来打印匹配的行*。此外,我们正在打印要添加的行,每行由\n*(换行符)字符分隔:

$ awk '/08-08-2021,SCRIP5,340/{print $0 "\n08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85"}' stocks.csv
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85

现在我们已经获得了匹配的行和附加的数据,让我们也打印剩余的行:

$ awk '/08-08-2021,SCRIP5,340/{print $0 "\n08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85"}1' stocks.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP5,340
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

在这里,命令末尾的“1”总是计算为true。因此,它打印文件的每一行。值得注意的是,匹配行被打印了两次。为了防止这种情况,我们将使用next命令**,它告诉awk跳过与我们的模式匹配的行

$ awk '/08-08-2021,SCRIP5,340/{print $0 "\n08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85";next}1' stocks.csv

请注意,awk命令没有对原始文件进行任何更改。但是,我们可以修改命令以更改临时文件,然后我们用它来替换原始文件:

$ awk '/08-08-2021,SCRIP5,340/{print $0 "\n08-08-2021,SCRIP6,49\n08-08-2021,SCRIP7,76\n08-08-2021,SCRIP8,85";next}1' stocks.csv > tempfile.csv && mv tempfile.csv stocks.csv
$ cat stocks.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

4.2. 当数据在另一个文件中时

同样,让我们看一下我们要插入的数据在另一个文件中的情况:

$ missing_lines=$(cat missing_data.csv)
$ echo "$missing_lines"
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
$ awk -v addpattern="$missing_lines" '/08-08-2021,SCRIP5,340/{print $0 "\n" addpattern;next}1' stocks.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

在这种方法中,我们首先将文件的内容存储在 Bash 变量中。然后,我们使用-v选项将此变量传递给awk*命令以进行进一步处理*。

5. 创建 Bash 脚本

最后,让我们也使用循环grep 命令编写一个 Bash 脚本解决方案:

$ cat insert_pattern.sh
#!/bin/bash
read -p "Enter the pattern: " pattern
>new_file.csv
while read line
do
    echo $line >>new.csv
    echo $line | grep -q "$pattern"
    [ $? -eq 0 ] && cat missing_data.csv >> new.csv
done < stocks.csv

在这里,我们从文件中读取记录  并将它们写入文件new.csv。然后,我们使用grep命令检查模式。如果模式匹配,我们会将missing_data.csv文件的数据附加到new.csv文件中。让我们执行脚本并检查文件的内容:

$ ./insert_pattern.sh
Enter the pattern: 08-08-2021,SCRIP5,340
$ cat new.csv
Date,TICKR,Price
08-08-2021,SCRIP1,104
08-08-2021,SCRIP2,107
08-08-2021,SCRIP3,105
08-08-2021,SCRIP4,110
08-08-2021,SCRIP5,340
08-08-2021,SCRIP6,49
08-08-2021,SCRIP7,76
08-08-2021,SCRIP8,85
08-08-2021,SCRIP9,100
08-08-2021,SCRIP10,35

如果需要,我们可以将新生成的文件的内容复制到原始文件中。