在文件中的模式之间匹配行并检查匹配行中的单词,如果没有找到,则添加单词

在文件中的模式之间匹配行并检查匹配行中的单词,如果没有找到,则添加单词

我有一个大文件,其内容如下:

--- 水果文件.txt---

fruit:

apple 
orange

fruit:

grapes
mango

fruit:

banana
cherries

--> 要求每个水果容器中都有苹果,如下所示

--- 水果文件.txt---

fruit:

apple

orange

fruit:

grapes

mango

apple

fruit:

banana

cherries

apple

尝试了不同的方法,有没有什么简单的方法可以实现这一点?

答案1

您可以按照以下方式处理该文件:

0。假设您的文件如下所示:

cat fruits_file.txt
fruit:

apple
orange

fruit:

grapes
mango

fruit:

banana
cherries

1.将文件内容转置为一行:

paste -s -d ' ' fruits_file.txt
fruit:  apple  orange  fruit:  grapes mango  fruit:  banana cherries

2.将上述命令的输出通过管道传输到sed并在字符串 前放置新行fruit:,通过管道传输输出|,然后使用sedgain 删除空行:

paste -s -d ' ' fruits_file.txt | sed 's/fruit:/\nfruit:/g' | sed '/^\s*$/d'
fruit:  apple  orange
fruit:  grapes mango
fruit:  banana cherries

3.将上述命令的输出通过管道传输到awk以便附加apple到缺少的行:

paste -s -d ' ' fruits_file.txt | sed 's/fruit:/\nfruit:/g' | sed '/^\s*$/d' | \
                      awk '{if (!/apple/) {printf "%s apple\n", $0;} else print}'
fruit:  apple  orange
fruit:  grapes mango
fruit:  banana cherries

4.将上述命令的输出通过管道传输到,sed以便将(表达式 1)多个空格替换为一个空格,并且(表达式 2)在每行末尾附加双空格:

paste -s -d ' ' fruits_file.txt | sed 's/fruit:/\nfruit:/g' | sed '/^\s*$/d' | \
                      awk '{if (!/apple/) {printf "%s apple\n", $0;} else print}' | \
                      sed -r -e 's/\s{1,9}/ /g' -e 's/\s*$/  /'
fruit: apple orange
fruit: grapes mango apple
fruit: banana cherries apple

5.将上述命令的输出sed再次通过管道传输到,以便(表达式 1)用换行符替换每个空格并(表达式 2)在每个fruit:字符串前添加换行符。然后将输出通过管道传输到,head以便删除最后两个空行:

paste -s -d ' ' fruits_file.txt | sed 's/fruit:/\nfruit:/g' | sed '/^\s*$/d' | \
                      awk '{if (!/apple/) {printf "%s apple\n", $0;} else print}' | \
                      sed -r -e 's/\s{1,9}/ /g' -e 's/\s*$/  /'  | \
                      sed -e 's/\s/\n/g' -e 's/fruit:/fruit:\n/' | head -n -2
fruit:

apple
orange


fruit:

grapes
mango
apple


fruit:

banana
cherries
apple

6.重定向上述命令的输出并创建一个新文件:

paste -s -d ' ' fruits_file.txt | sed 's/fruit:/\nfruit:/g' | sed '/^\s*$/d' | \
                      awk '{if (!/apple/) {printf "%s apple\n", $0;} else print}' | \
                      sed -r -e 's/\s{1,9}/ /g' -e 's/\s*$/  /'  | \
                      sed -e 's/\s/\n/g' -e 's/fruit:/fruit:\n/' | head -n -2 \
                      > fruits_new.txt
cat fruits_new.txt
fruit:

apple
orange


fruit:

grapes
mango
apple


fruit:

banana
cherries
apple

答案2

更新:

如果您想保留单词的位置(如果该单词已经存在),否则将其附加到容器的末尾,请尝试使用以下命令:

sed '/^$/d' fruits_file.txt | tr '\n' ' ' | tr -s ' ' | sed 's/fruit:/\nfruit:/g' | sed '/apple\|^$/! s/$/apple/' | tr ' ' '\n'> final_fruits.txt

旧答案

如果位置apple不重要,请使用以下内容。

sed -i.bak '/^$/d;/apple/d;s/fruit:/\nfruit:\napple/g' fruits_file.txt

-i.bak:用于制作备份文件。在本例中:fruits_file.txt.bak

'/^$/d':将删除空白行(这是可选的)。

'/apple/d':删除任何包含 的行apple

s/fruit:/\nfruit:\napple/gapple在 后添加新行fruit:

答案3

由于文件很大,我们将单独处理每个容器,而不是将整个文件加载到内存中。我们可以在 Python3 中轻松完成此操作。将其保存在,process.py并将数据保存在fruits_file.txt

import sys

# This function checks if "apple" not in container then append it.
def add_apple_and_print(container):
    if container is not None:
        if "apple" not in container:
            container.append('apple')

        print("\nfruit:\n")
        print("\n\n".join(container))

# Open the file for reading
with open(sys.argv[1]) as f:

     container = None                     # Initialize the container with None
     for line in f:                       # Read line by line
        line = line.strip()               # Remove trailing spaces
        if len(line) > 0:
            if line == "fruit:":
                add_apple_and_print(container)  # Print privious container
                container = []                  # Create a new container for current fruit section
            else:
                container.append(line)          # Add fruits to container

     add_apple_and_print(container)             # Print last container

然后

python3 process.py fruits_file.txt > fruits_file_with_apple.txt

答案4

您可能想找到一些命令来实现这一点...但我认为借助一些功能性文本编辑器做这些事情会更容易。我建议使用 Visual Studio Code。您可以使用类似的工具Find and Replace。您可以找到每个fruit:并将其替换为:

fruit:

apple

但如果它已经有一些苹果,那么在这些“水果容器”中你就可以得到一些重复的。

相关内容