regex 尝试用替换字符串替换sed匹配模式的一部分

fae0ux8s  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(122)

试着把我的个人科幻书PDF转换成电子书。我将所有行收集到一个连续的段落中的中间步骤是正确的排序,但我最终得到了一些不正确的字符串序列,因为它们是从转换工具中输出的,或者是我的排序过程中的随机情况。
在以下测试脚本中确定了违规字符串序列:

{
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)

字符串
我的期望输出应该是这样的(* 不带'^'s * 的行):

"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!"
             ^^^


问题是,我在模式之前和之后指定了一个字符(alphanum)的存在,但我只想替换正在交换的字符串,保留在这些示例之前或之后匹配的字符。
由于我对sed的理解有限,唯一一个与我自己的问题接近的帖子是this,但我无法破译它,更不用说尝试自己的手使用技术解决我的问题了。
我更喜欢做一个post-collection sed操作,而不是重新编写我已经很复杂的awk逻辑来进行段落识别和校对。
谁能告诉我如何在这些场景中做到这一点?

uxh89sit

uxh89sit1#

您可能希望使用捕获组,从而可以在脚本的后半部分使用数字反向引用来引用一组括号内的内容。
一个简单的例子:

$ echo 'ABC' | sed -E 's/(A)(B)(C)/\1x\2y\3/'
AxByC

字符串
地点:

  • -E-启用扩展正则表达式,并允许使用parens来指定捕获组;如果没有-E,则需要转义每个paren(例如,sed 's/\(A\)\(B\)\(C\)/\1x\2y\3/'
  • (A)(B)(C)-(定义)第一、第二和第三捕获组
  • \1\2\3-(使用/参考)第1、第2和第3个捕获组

关注将逗号移动到引号字符串的“外部”的要求...

  • 需要定义带引号的字符串的开始和结束
  • 我需要定义这对引号中的所有内容
  • 假定没有嵌入双引号

再看一对要求:

#    ",body_of_quote"    =>    ,"body_of_quote"

sed -E 's/",([^"]*")/,"\1/g'
          ^^ start of quote and initial comma
            ^^^^^^^^ capture group consisting of 0-or-more characters that are not a double quote, end of quote
                     ^^ reverse order of comma and double quote
                       ^^ copy of capture group

#    "body_of_quote,"    =>    "body_of_quote",

sed -E 's/("[^"]*),"/\1",/g'
          ^^^^^^^^ capture group consisting of start of quote plus 0-or-more characters and are not a double quote
                  ^^ comma and end of quote
                     ^^ copy of capture group
                       ^^ reverse order of comma and double quote


使用文件作为示例输入:

$ cat sample.dat
"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"!


测试sed脚本:

$ sed -E 's/",([^"]*")/,"\1/g' sample.dat | sed -E 's/("[^"]*),"/\1",/g' | grep -Ei 'he said'
"I will do it", he said.
He said,"Be there ... or be square!"
He said,"Be there ... or be square!"


合并为一个复合sed脚本:

$ sed -E 's/",([^"]*")/,"\1/g; s/("[^"]*),"/\1",/g' sample.dat | grep -Ei 'he said'
"I will do it", he said.
He said,"Be there ... or be square!"
He said,"Be there ... or be square!"

注意事项:

  • 类似的方法可用于在带引号的字符串前添加空格的要求
  • 不确定我是否理解了最后一行的要求(在!之后添加一个空格?)),但一个捕获组可能也会在那里派上用场
  • 如果你在运行其余的sed脚本时遇到问题,那么我建议你问一个新的问题,这个问题只关注你遇到问题的sed脚本
  • 你已经声明你不想修改你当前的awk脚本;请记住,我们在这里使用sed * 所做的一切都可以在awk中完成,并且会更有效(即,不需要为sed脚本生成单独的(子)进程)
yb3bgrhw

yb3bgrhw2#

使用sed

$ sed -E 's/(")(,)?([^"]*)((,)(") )?/\2\1\3\6\5/;
s/([[:punct:]])(")/\1 \2/;
s/("[^"]*)(")([[:punct:]])($| )/\1\3\2\4/;
s/",/& /' input_file
"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!"

字符串

相关问题