如何使用sed搜索存储在保持空间中的单词?

Wil*_*ard 3 sed perl text-processing regular-expression

这是一个sed特定的问题;我很清楚它可以用其他工具完成,但我正在努力扩展我的sed.

如何使用sed全局引用(实际上是反引号)脚本中未指定的单词?这个词被保存在保持空间中。

我想要的是这样的:

s/word/`&`/g
Run Code Online (Sandbox Code Playgroud)

但诀窍是,word将不包含在 sed 脚本中,而是包含在保留空间中。所以它看起来更像是:

H
g
s/^\(.*\)\n\(.*\)\1\(.*\)$/\2`\1`\3/
Run Code Online (Sandbox Code Playgroud)

这将引用保留空间中保存的单词的一次出现。我想引用所有这些,但我不能只添加一个g标志,因为它使用反向引用而不是静态正则表达式的方式。

H
g
s/^\(.*\)\n\(.*\)\1\(.*\)\1\(.*\)$/\2`\1`\3`\1`\4/
Run Code Online (Sandbox Code Playgroud)

这会处理单词的两次出现,但一次失败,并且忽略不止一次。

我想我可以使用一些干净简单的东西,比如:

s//`&`/g
Run Code Online (Sandbox Code Playgroud)

但这会重用上次使用的regex,而不是匹配的内容。(这是有道理的。)

有什么办法sed可以做我想做的事吗?(实际上我很想知道这在 中有多容易perl,但我仍然想看看如何在 中做到这一点sed。)


更新

并不是说这个问题需要它,但我想我会提供更多关于我在提出这个问题时到底在做什么的背景:

我有一个很大的文档文本文件,其中的某些部分需要压缩并汇总到一个asciidoc表格中。由于Description:Prototype:行等,这很容易,所以我实际上编写了一个快速sed脚本来为我完成所有解析。它工作得很好——但它缺少的一件事是我想对与该Description行中列出的参数匹配的行中的单词进行反引号Prototype。原型线看起来像这样:

Prototype: some_words_here(and, arg, list,here)
Run Code Online (Sandbox Code Playgroud)

有向上的200个不同的条目中我被输出表(和源文件包括比很多更多的文本),并且仅需要每个arglist中被用于反引号引号匹配的单词上的单个线。为了让事情变得更棘手,有些参数不在描述行中,有些在不止一次,有些参数是空的()。

然而,考虑到有时 arg 会匹配单词的一部分,我不想被反引号,有时 arg 名称是一个常用词(如from),我只想在它被用于在解释该功能的使用的上下文中,自动化解决方案实际上根本不适合,而我过去常常vim在一些棘手的宏的帮助下半手动完成这项工作。:)

cha*_*aos 5

那是一件很难的事。假设你有file这样的:

$ cat file
word
line with a word and words and wording wordy words.
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • 第 1 行:是应保留在保留空间中并引用到 的搜索模式`word`
  • 第 2 行:是全局搜索和替换的行。

sed命令:

sed -n '1h; 2{x;G;:l;s/^\([^\n]\+\)\n\(.*[^`]\)\1\([^`]\)/\1\n\2`\1`\3/;tl;p}' file
Run Code Online (Sandbox Code Playgroud)

说明

  • 1h; 将第一行保存到保留空间(这是我们要搜索的等待)。
    • 保持空间包含: word
  • 2{...} 适用于第二行。
  • x; 交换模式空间和保持空间。
  • G;将保持空间附加到模式空间。在我们现在的模式空间中:
$ cat file
word
line with a word and words and wording wordy words.
Run Code Online (Sandbox Code Playgroud)
  • :l;设置一个称为l点的标签供以后使用。
  • s/// 在上述模式空间中进行实际搜索/替换:
    • ^\([^\n]\+\)\n在“模式行”中搜索所有^不是换行符[^\n](一次或多次\+)的字符(从行首),直到换行符\n。这现在存储在反向引用中\1。它包含“模式线​​”。
    • (.*[^`])搜索任何.*后跟一个字符的字符,它不是反引号[^`]。这存储在\2. \2包含 now: line with a word and words and wording wordy, 直到最后一次出现word, 因为...
    • \1是下一个搜索词(反向引用\1, word),因此是“模式行”包含的内容。
    • ([^`])这之后是另一个不是反引号的字符;保存以供参考\3。如果我们不这样做(以及\2上面的部分),我们将在无限循环中结束word,一遍又一遍地引用相同的-> ````word````,因为s///总是会成功并tl;跳回:l(见下文tl;)。
    • \1\n\2\1\3以上所有内容都被反向引用所取代。第二个\1是我们应该引用的(注意第一个引用是“模式线”)。
  • tl;如果s///成功(我们替换了一些东西)跳转到被调用的标签l并重新开始,直到没有更多的东西可以搜索和替换。当所有出现的单词都被替换/引用时,就是这种情况。
  • p; 全部完成后,打印更改后的行(模式空间)。

输出:

$ sed -n '1h; 2{x;G;:l;s/^\([^\n]\+\)\n\(.*[^`]\)\1\([^`]\)/\1\n\2`\1`\3/;tl;p}' file
word
line with a `word` and `word`s and `word`ing `word`y `word`s.
Run Code Online (Sandbox Code Playgroud)