![在文件中的模式之间匹配行并检查匹配行中的单词,如果没有找到,则添加单词](https://linux22.com/image/928222/%E5%9C%A8%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%97%B4%E5%8C%B9%E9%85%8D%E8%A1%8C%E5%B9%B6%E6%A3%80%E6%9F%A5%E5%8C%B9%E9%85%8D%E8%A1%8C%E4%B8%AD%E7%9A%84%E5%8D%95%E8%AF%8D%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%E6%89%BE%E5%88%B0%EF%BC%8C%E5%88%99%E6%B7%BB%E5%8A%A0%E5%8D%95%E8%AF%8D.png)
我有一个大文件,其内容如下:
--- 水果文件.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:
,通过管道传输输出|
,然后使用sed
gain 删除空行:
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/g
:apple
在 后添加新行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
但如果它已经有一些苹果,那么在这些“水果容器”中你就可以得到一些重复的。