You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用sed替换匹配模式中的指定部分并保留其他字符?

问题描述

我正尝试将个人科幻书籍PDF库转换为epub格式。在将所有行合并为连续段落的中间步骤中,整理过程正常,但由于转换工具输出或整理过程中的随机情况,出现了一些错误的字符串序列。

问题字符串序列如下测试脚本所示:

{
cat <<-EnDoFiNpUt
"I will do it," he said.
He said,"Be there ... or be square!"
He said",Be there ... or be square!"
They yelled:"Why now?"
Tell them "No"!{end-of-lineORspace}
EnDoFiNpUt
} |
sed 's+[a-zA-Z0-9]",[A-Z]+{somethingThree}+g' |      (line 3)
sed 's+[a-zA-Z0-9],"[A-Z]+{somethingTwo}+g' |      (line 2)
sed 's+[a-zA-Z0-9]:"[A-Z]+{somethingFour}+g' |      (line 4)
sed 's+[a-zA-Z0-9]"[!]$+{somethingFive}+g'  |      (line 5)
sed 's+[a-zA-Z0-9],"\ [A-Z]+{somethingOne}+g'      (line 1)

期望输出如下(不含带^的行):

"I will do it", he said.
             ^^^
He said, "Be there ... or be square!"
       ^^^
He said, "Be there ... or be square!"     (same result for 2nd scenario)
       ^^^
They yelled: "Why now?"
           ^^^
Tell them "No!"
             ^^^

核心问题:指定了匹配模式前后的字母数字字符,但只想替换需要调换的字符串部分,保留匹配到的前后字符。希望用整理后的sed操作解决,不修改已有的复杂AWK段落识别与整理逻辑。

解决方案

你需要用sed的捕获组功能,把要保留的字符用\(pattern\)包裹,替换时用\1、\2来引用这些捕获到的内容,只修改中间错误的部分。以下是针对每个场景的修正sed命令:

对应各个错误场景的sed命令

  1. 修正said,"Be → said, "Be
sed 's+\([a-zA-Z0-9]\),"\([A-Z]\)+\1, "\2+g'
  • 解释:\([a-zA-Z0-9]\)捕获单词末尾的字母数字,\([A-Z]\)捕获引号后的大写首字母,替换时在逗号和引号之间加空格,保留前后捕获的内容。
  1. 修正said",Be → said, "Be
sed 's+\([a-zA-Z0-9]\)",\([A-Z]\)+\1, "\2+g'
  • 解释:捕获单词末尾字符和引号后的大写首字母,把",替换成, 。
  1. 修正yelled:"Why → yelled: "Why
sed 's+\([a-zA-Z0-9]\):"\([A-Z]\)+\1: "\2+g'
  • 解释:捕获冒号前的字符和引号后的大写首字母,在冒号和引号之间加空格。
  1. 修正"No"! → "No!"
sed 's+\([a-zA-Z0-9]\)"\(!\)$+\1"\2+g'
  • 解释:捕获引号前的字符和末尾的感叹号,把感叹号移到引号内部。

合并后的完整命令

可以把这些sed命令合并成一条管道,减少进程开销:

{
cat <<-EnDoFiNpUt
"I will do it," he said.
He said,"Be there ... or be square!"
He said",Be there ... or be square!"
They yelled:"Why now?"
Tell them "No"!
EnDoFiNpUt
} |
sed -e 's+\([a-zA-Z0-9]\),"\([A-Z]\)+\1, "\2+g' \
    -e 's+\([a-zA-Z0-9]\)",\([A-Z]\)+\1, "\2+g' \
    -e 's+\([a-zA-Z0-9]\):"\([A-Z]\)+\1: "\2+g' \
    -e 's+\([a-zA-Z0-9]\)"\(!\)$+\1"\2+g'

运行后就能得到你期望的格式:

"I will do it," he said.
He said, "Be there ... or be square!"
He said, "Be there ... or be square!"
They yelled: "Why now?"
Tell them "No!"

内容的提问来源于stack exchange,提问作者Eric Marceau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 22:22:36