Đánh dấu từ chứa vần của câu thơ

Từ lâu anh đã muốn thêm tính năng trích dẫn một câu thơ vào kết quả tìm kiếm âm tiết theo vần. Nhân hôm trời trở lạnh, anh tranh thủ lấy ít ca dao và truyện thơ trung đại về làm dữ liệu.

Sở dĩ anh lấy hai món kia là vì thứ nhất là không lo về bản quyền. Thứ hai là số lượng câu rất lớn, tổng cộng anh đã lấy được hàng chục nghìn dòng. Và quan trọng là nó ở thể lục bát và song thất lục bát. Đây là thể loại có cấu trúc khá chặt chẽ, anh có thể xác định được vần mà không cần tốn nhiều công sức.

Anh tự quy ước vị trí của vần trong câu lục bát là 6/6, 4/8, 6/8 và 8/8. Còn trong câu song thất là 5/7-1, 7/7-1, 5/7-2 và 7/7-2.

Ví dụ:

“Trăm năm trong cõi người ta [6/6]
Chữ tài chữ mệnh khéo [6/8] ghét nhau [8/8]

“Con mèo trèo lên cây táo,
Mồ hôi chưa ráo [4/8], áo cụt chưa khô”

“Cùng trông lại mà cùng [5/7-1] chẳng thấy [7/7-1],
Thấy xanh xanh những mấy [5/7-2] ngàn dâu [7/7-2].

Sau khi đã xác định được vần trong câu, anh cho nó vào cơ sở dữ liệu để sau này tìm kiếm cho tiện.

Nhưng đánh dấu vần đã biết trong câu thơ hoá ra lại phức tạp hơn anh nghĩ. Bình thường thì chỉ cần làm một phát thay thế như này:

re.sub(rf'\b({syllable})\b', '<strong>\\1</strong>', line, flags=re.I)

Nhưng đời đâu phải lúc nào cũng dễ dàng. Nhiều khi trong câu lại có nhiều âm tiết trùng với âm chứa vần. Ví dụ:

“Ta về ta rủ bạn ta
Ruộng ta ta cấy, vườn ta ta trồng”

Nếu đánh dấu âm “ta” thì trong câu 8 sẽ có hẳn bốn chữ “ta” được in đậm.

Cũng may là anh cũng tìm ra cách:

import re

def hilight_syllable(line, syllable, position):
	line = line.strip()

	counting = re.findall(rf'\b{syllable}\b', line, flags=re.I)
	if (len(counting)) == 1:
		line = re.sub(rf'\b({syllable})\b', '<strong>\\1</strong>', line, flags=re.I)
	else:
		match position:
			case '6/8' | '5/7-1' | '5/7-2':
				repeat = 2
			case '4/8':
				repeat = 4
			case _:
				repeat = 0

		line = re.sub(rf'\b({syllable})\b(([^\w\s]+)?( [\w]+([^\w\s]+)?){{{repeat}}})$', '<strong>\\1</strong>\\2', line, flags=re.I)

	return line

Chạy thử:

test = [
	['Ta về ta rủ bạn ta', 'ta', '6/6'],
	['Ruộng ta ta cấy, vườn ta ta trồng', 'ta', '6/8'],
	['Khóc vì nỗi thiết tha sự thế', 'thế', '7/7-1'],
	['Ai bày trò bãi bể nương dâu?', 'bể', '5/7-2'],
	['Duyên hội ngộ, đức cù lao,', 'lao', '6/8'],
	['Bên tình bên hiếu, bên nào nặng hơn?', 'hơn', '8/8'],
]

for line in test:
	print(hilight_syllable(line[0], line[1], line[2]))

Cho ra kết quả:

Ta về ta rủ bạn <strong>ta</strong>
Ruộng ta ta cấy, vườn <strong>ta</strong> ta trồng
Khóc vì nỗi thiết tha sự <strong>thế</strong>
Ai bày trò bãi <strong>bể</strong> nương dâu?
Duyên hội ngộ, đức cù <strong>lao</strong>,
Bên tình bên hiếu, bên nào nặng <strong>hơn</strong>?

Trên Dự án S:

Ta về ta rủ bạn ta / Ruộng ta ta cấy, vườn ta ta trồng