使用sed
,我想按以下方式替换模式:
--- >>> +++
--+-- >>> ++-++
--+-+-- >>> ++-+-++
--+-+-+-- >>> ++-+-+-++
...
--(+-)^n- >>> ++(-+)^n+
我正在操作的字符串是 + 和 - 的任意列表。
--+++-+--+--++-+--++--+-+--++--+-++-+-
我尝试过这个,但它不起作用。
sed '/--\<+-\>*-/{s/+/A/g;s/-/+/g;s/A/-/g}'
对于上面的示例,我期望以下输出:
--+++-+--+--++-+--++--+-+--++--+-++-+- (input)
--+++-+++-++++-+--++++-+-++++--+-++-+- (output)
!!!!! !!!!!!!
(感叹号表示更改的区域。)
答案1
您尝试仅修改地址中正则表达式匹配的部分,但是一旦地址匹配,替换就会影响整行。诀窍是当您应用变换时,仅在模式空间中包含您想要更改的内容。这个命令的作用是:
sed '/--\(+-\)*-/{:a;h;s/.*\(--\(+-\)*-\).*/\1/;y/+-/-+/;G;s/\(.*\)\n\(.*\)--\(+-\)*-\(.*\)/\2\1\4/;/--\(+-\)*-/ba}' <<< '--+++-+--+--++-+--++--+-+--++--+-++-+-'
我一点更容易阅读:
/--\(+-\)*-/ { # Match a line containing the pattern
:start # Label to branch back to
h # Copy pattern space to hold space
s/.*\(--\(+-\)*-\).*/\1/ # Remove everything but pattern
y/+-/-+/ # Swap + and -
G # Append hold space to pattern space
s/\(.*\)\n\(.*\)--\(+-\)*-\(.*\)/\2\1\4/ # Rearrange pattern space
/--\(+-\)*-/b start # If there are more occurrences, branch to start
}
请注意,这可能不适用于评论,y
似乎有问题。
使用示例字符串进行测试:
$ sed -f sedscr <<< '--+++-+--+--++-+--++--+-+--++--+-++-+-'
--+++-+++-++++-+--++++-+-++++--+-++-+-
关于问题中的 sed 命令有两点需要提及:
\<
并\>
匹配单词边界,但您只想分组:\(\)
- 如果要更改字符的直接映射,则可以使用转换命令
y
而不是多次替换