【问题标题】:How to process a regular expression after being evaluated (sed)评估后如何处理正则表达式(sed)
【发布时间】:2019-03-22 14:03:42
【问题描述】:

我需要用每个字符加上@符号替换正则表达式的每个字符,评估一次

例如:

如果正则表达式为: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@

提前谢谢你。

最好的问候, 奥克塔维奥

【问题讨论】:

    标签: regex bash shell ksh


    【解决方案1】:

    Perl 助你一臂之力!

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

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

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

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

    【讨论】:

    • 这是(到目前为止)正确限制将“@”添加到正则表达式匹配项的唯一建议。例如,echo "POSA____OOPS____POSB" | perl -pe 's/(POS[AB])/$1 =~ s:(.):$1@:gr/ge' 打印“P@O@S@A@____OOPS____P@O@S@B@”(应该如此)。
    • 非常感谢您的回答。我无法让它工作,它给了我以下错误: $ echo "POSA_____POSB" | perl -pe 's/(POS[AB])/$1 =~ s:(.):$1@:gr/ge' 在 -e 第 1 行,“s:(.):$1@ 附近的运算符预期的位置找到裸字-e 第 1 行的 :gr 语法错误,靠近“s:(.):$1@:gr” 执行 -e 由于编译错误而中止。
    • @OctavioRodriguezPerez:您的 Perl 可能很古老(2011 年之前发布的 5.14 之前的版本)。查看更新。
    【解决方案2】:

    回显“POSA_____POSB”| sed "s/[^_]/&@/g"

    回显“POSA_____POSB”| sed "s/[POSAB]/&@/g"

    【讨论】:

    • 这将在每个匹配的字符之后放置一个“@”,无论它是否是整体匹配的一部分。例如,echo "OOPS" | sed "s/[POSAB]/&@/g" 打印“O@O@P@S@”。
    【解决方案3】:

    试试这个正则表达式:

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

    输出:

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

    【讨论】:

    • 这将在每个匹配的字符之后放置一个“@”,无论它是否是整体匹配的一部分。例如,echo "OOPS" | sed "s/[A-Z]/&@/g" 打印“O@O@P@S@”。
    【解决方案4】:

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

    解决方案 1

    编辑:编辑以匹配 cmets

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

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

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

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

    为了清楚起见,为每个操作单独的“{}”和明确的print

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

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

    第二个gsub 用于将修改后的str 放入$0(匹配整个记录/行)。

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

    [] 引入要匹配的字符集:任何字符的每次出现都会被匹配。上面的表达式表示awk 匹配任何“POSAB”的出现。

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

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

    解决方案 2

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

    解释:

    否定的意思是:匹配除了'[]'之间的字符之外的任何东西。 '^' 字符必须作为第一个字符出现,就在打开 '[' 之后。

    旁注:

    另外,最好使用[POSAB]?[POSAB]{1} 直接表明您希望一次匹配一个字符。

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

    【讨论】:

    • 这些将在每个匹配的字符后放置一个“@”,无论它是否是整体匹配的一部分。例如,echo "OOPS" | awk '{gsub(/[POSAB]/,"&@");}1' 打印“O@O@P@S@”。
    • @GordonDavisson:编辑答案以更好地满足要求。
    • 感谢您的详细解答。问题是它必须与任何正则表达式一起使用,“POSA_____POSB”的情况只是一个例子。一个更合适的例子是: echo "POSBAAAPOSABBBPOSCPOSB" 会返回这个: P@O@S@B@AAAP@O@S@A@BBBPOSCP@O@S@B@ 这是一个例子,但是他的正则表达式可以包含任何字符,而不仅仅是字母数字字符。
    【解决方案5】:

    您可以使用给定的示例

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多