如何使用 sed 搜尋儲存在保持空間中的單詞?
這是一個
sed
特定的問題;我很清楚它可以使用其他工具來完成,但我正在努力擴展我對sed
.如何使用
sed
全域引用(實際上是反引號)腳本中未指定的單詞?單詞被保存在保存空間中。我想要的是這樣的:
s/word/`&`/g
但訣竅是,
word
將不包含在 sed 腳本中,而是包含在保留空間中。所以它看起來更像:H g s/^\(.*\)\n\(.*\)\1\(.*\)$/\2`\1`\3/
這將引用保存空間中保存的單詞的一次出現。我想引用所有這些,但我不能只添加一個
g
標誌,因為它使用反向引用而不是靜態正則表達式。H g s/^\(.*\)\n\(.*\)\1\(.*\)\1\(.*\)$/\2`\1`\3`\1`\4/
這處理了單詞的兩次出現,但一次失敗,並且忽略了不止一次。
我想我可以使用一些乾淨簡單的東西,比如:
s//`&`/g
但這重用了最後使用的regex,而不是它匹配的內容。(這是有道理的。)
有什麼辦法
sed
可以做我想做的事嗎?(實際上我很想看看這在 中有多容易perl
,但我仍然想看看如何在 中做到這一點sed
。)更新
並不是說這個問題需要它,但我想我會在提出這個問題時就我到底在做什麼提供更多背景資訊:
我有一個很大的文件文本文件,其中某些部分需要壓縮並彙總到一個
asciidoc
表格中。Description:
由於和Prototype:
線等,這很容易,所以我實際上編寫了一個快速sed
腳本來為我完成所有解析。它工作得很好——但它缺少的一件事是我想反引號該Description
行中與該行中列出的參數匹配的單詞Prototype
。原型線看起來像這樣:Prototype: some_words_here(and, arg, list,here)
我輸出的表中有超過 200 個不同的條目(源文件包含的文本比這多得多),每個 arglist 只需要用於在單行上反引號引用匹配的單詞。更棘手的是,有些參數不在描述行中,有些在不止一次,有些參數列表是空的()。
但是,考慮到有時 arg 會匹配單詞的一部分,我不想反引號,有時 arg 名稱是一個常用詞(如
from
),我只想在它用於在解釋函式使用的上下文中,自動化解決方案實際上根本不適合,我過去常常vim
在一些棘手的宏的幫助下半手動地完成這項工作。:)
那是一個艱難的過程。假設你有
file
這樣的:$ cat file word line with a word and words and wording wordy words.
在哪裡:
- 第 1 行:是應該保留在保留空間中並引用到的搜尋模式
word
。- 第 2 行:是全域查找和替換的行。
sed
命令:sed -n '1h; 2{x;G;:l;s/^\([^\n]\+\)\n\(.*[^`]\)\1\([^`]\)/\1\n\2`\1`\3/;tl;p}' file
說明:
1h;
將第一行保存到保留空間(這是我們要搜尋的等待)。
- 容納空間包含:
word
2{...}
適用於第二行。
x;
交換模式空間和保持空間。
G;
將保持空間附加到模式空間。在我們現在擁有的模式空間中:word # I will call this line the "pattern line" from now on line with a word and words and wording wordy words.
:l;``l
為以後設置一個稱為點的標籤。
s///
在上述模式空間中進行實際搜尋/替換:
^\([^\n]\+\)\n``^
在“模式行”中搜尋所有不是換行符[^\n]
(一次或多次)的字元(從行的開頭\+
),直到換行符\n
。這現在儲存在 back-reference 中\1
。它包含“模式線”。(.*[^
])搜尋
.*後跟一個字元的任何字元,該字元不是反引號
[^]
。這儲存在\2
.\2
包含現在: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.