簡體   English   中英

在sed中執行由反向引用定義的命令

[英]Execute command defined by backreference in sed

我正在創建一個完全基於sed的原始實驗模板引擎(僅出於個人目的)。 我已經嘗試了好幾個小時了,現在要做的一件事是用它們包含的命令輸出替換某些文本模式。

為了澄清,如果輸入行看起來像這樣

Lorem {{echo ipsum}}

我將看到sed輸出看起來像這樣:

Lorem ipsum

我最接近的是:

echo 'Lorem {{echo ipsum}}' | sed 's/{{\(.*\)}}/'"$(\\1)"'/g'

這不起作用。

然而,

echo 'Lorem {{echo ipsum}}' | sed 's/{{\(.*\)}}/'"$(echo \\1)"'/g'

給我

Lorem echo ipsum

我不太了解這里發生了什么。 為什么我可以將后向引用賦予echo命令,但不能在$()中評估整個后向引用? \\\\ 1什么時候得到評估? 我嘗試使用純sed甚至可以實現的目標嗎?

請記住,對我來說,很清楚,使用其他工具可以輕松實現我要實現的目標。 但是,我對純sed是否可以實現這一點非常感興趣。

謝謝!

您的嘗試不起作用的原因是$()在調用sed之前已被外殼擴展。 因此,它不能使用sed最終將要捕獲的反向引用。

使用GNU sed(而不是POSIX sed)可以做這種事情。 主要技巧是GNU sed在s命令中帶有一個e標志,使它用作為shell命令執行的模式空間的結果替換模式空間(整個空間)。 這意味着

echo 'echo foo' | sed 's/f/g/e'

打印goo

可以將其用於您的用例,如下所示:

echo 'Lorem {{echo ipsum}}' | sed ':a /\(.*\){{\(.*\)}}\(.*\)/ { h; s//\1\n\3/; x; s//\2/e; G; s/\(.*\)\n\(.*\)\n\(.*\)/\2\1\3/; ba }'

sed代碼的工作方式如下:

:a                                    # jump label for looping, in case there are
                                      # several {{}} expressions in a line
/\(.*\){{\(.*\)}}\(.*\)/ {            # if there is a {{}} expression,
  h                                   # make a copy of the line
  s//\1\n\3/                          # isolate the surrounding parts
  x                                   # swap the original back in
  s//\2/e                             # isolate the command, execute, get output
  G                                   # get the outer parts we put into the hold
                                      # buffer
  s/\(.*\)\n\(.*\)\n\(.*\)/\2\1\3/    # rearrange the parts to put the command
                                      # output into the right place
  ba                                  # rinse, repeat until all {{}} are covered
}

這利用了正則表達式中sed的貪婪匹配來始終捕獲一行中的最后一個{{}}表達式。 請注意,如果一行中有多個命令,而后一個命令具有多行輸出,則會遇到困難。 處理這種情況將需要定義一個標記,即不允許嵌入在數據中的命令作為其輸出的一部分,並且不允許包含模板。 我建議使用類似{{{}}} ,這將導致

sed ':a /\(.*\){{\(.*\)}}\(.*\)/ { h; s//{{{}}}\1{{{}}}\3/; x; s//\2/e; G; s/\(.*\)\n{{{}}}\(.*\){{{}}}\(.*\)/\2\1\3/; ba }'

其背后的原因是,如果嵌入式命令進一步打印{{}}項,則模板引擎無論如何都會遇到麻煩。 不能強制執行此約定,但是無論如何,傳遞給此模板引擎的任何代碼最好都來自受信任的來源。

請注意,我不確定這整個事情是否是理智的想法1 您不打算在任何生產代碼中使用它,對嗎?

1但是,我很確定這是否是一個理智的想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM