如何在求值后处理正则表达式 (sed)

How to process a regular expression after being evaluated (sed)

我需要用每个字符加上 @ 符号来替换正则表达式的每个字符,计算后

例如:

如果正则表达式为:POS[AB]

输入文本为:POSA_____POSB

我想得到这个结果:P@O@S@A@_____P@O@S@B@

请使用 sedawk

我试过这个:

$ echo "POSA_____POSB" | sed "s/POS[AB]/&@/g"

POSA@_____POSB@

$ echo "POSA_____POSB" | sed "s/./&@/g"

P@O@S@A@_@_@_@_@_@P@O@S@B@

但我需要的是:

P@O@S@A@_____P@O@S@B@

提前致谢。

此致, 奥克塔维奥

Perl 求救!

perl -pe 's/(POS[AB])/ =~ s:(.):@:gr/ge'

/e 将替换解释为代码,它包含另一个替换,用自身加上 ​​@.

替换每个字符

在 5.14 之前的古代 Perls 中(即没有 /r 修饰符),你需要使用更复杂的东西

perl -pe 's/(POS[AB])/$x = ; $x =~ s:(.):@:g; $x/ge'

回声"POSA_____POSB" | sed "s/[^_]/&@/g"

回声"POSA_____POSB" | sed "s/[POSAB]/&@/g"

试试这个正则表达式:

echo "POSA_____POSB" | sed "s/[A-Z]/&@/g"

输出:

P@O@S@A@_____P@O@S@B@

您可以使用 awk 将正则表达式模式替换为 sub(第一个匹配的子字符串,sed "s///")或 gsub(替换匹配的子字符串在全球范围内,sed "s///g") 命令。 sedawk 之间的正则表达式本身没有区别。在你的情况下你想要:

解决方案 1

编辑:编辑以匹配评论

以下awk将限制替换为给定的子字符串(例如'POSA_____POSB'):

 echo "OOPS POSA_____POSB" | awk '{str="POSA_____POSB"}; {gsub(/[POSAB]/,"&@",str)}; {gsub(/'POSA_____POSB'/, str); print [=10=]} '

如果您的输入仅包含匹配的字符串,试试这个:

echo "POSA_____POSB" |  awk '{gsub(/[POSAB]/,"&@");}1'
解释:

为清楚起见,为每个操作使用单独的“{}”和显式 print

gsub 接受 3 个参数 gsub(pattern, substitution [, target]),其中目标必须是可变的(gsub 将就地更改它并将结果存储在那里)。

我们使用名为 'str' 的变量,并在进行任何替换之前用值(您的字符串)对其进行初始化。

第二个 gsub 用于将修改后的 str 放入 [=28=](匹配整个 record/line)。

表达式默认为 greedy --- 它们将匹配可能的最长字符串。

[] 引入要匹配的字符集:任何字符的每次出现都将被匹配。上面的表达式说 awk 来匹配任何 "POSAB".

的每次出现

您的第一个正则表达式没有按预期工作,因为您告诉 sed 匹配以任何 [AB] 结尾的 POS(一次匹配整个字符串)。 在另一个表达式中,您告诉它在使用时匹配任何单个字符(包括“_”):'.'(点)。

如果您想推广此解决方案,您可以使用:[\w] 表达式,它将匹配 [a-zA-Z0-9_][a-z][A-Z][0-9] 中的任何一个分别匹配小写字母、大写字母和数字。

解决方案 2

请注意,您可以使用 [^] 否定字符集,因此:[^_] 也适用于这种特殊情况。

解释:

否定表示:匹配除'[]'之间的字符以外的任何字符。 '^' 字符必须作为第一个字符出现,紧跟在打开 '['.

之后

旁注:

另外,使用 [POSAB]?[POSAB]{1}.

直接指示您一次匹配一个字符可能是个好主意

另请注意,sed 的某些实现可能需要 -r 切换为使用扩展(更复杂)的正则表达式。

根据给定的示例,您可以使用

echo "POSA_____POSB" | sed -r 's/POS([AB])/P@O@S@@/g'

对于更复杂的表达式,这将失败。
当你的输入没有\v\r时,你可以使用

echo "POSA_____POSB" | 
   sed -r 's/POS([AB])/\v&\r/g;  :loop;s/\v([^\r])/@\v/;t loop; s/[\v\r]//g'