【问题标题】:Replace multiple Character between two characters using sed or perl使用 sed 或 perl 替换两个字符之间的多个字符
【发布时间】:2020-11-15 01:36:16
【问题描述】:

我想替换字符,例如',' 和 ';'仅在两个连续的 '[' 和 ']' 之间使用 sed 或 perl linux 命令。

输入

abcd,e%sa,@ert&,,qet|,[,,efeg,sy bh|slhg],oiuy#,[abh,ohg;,a oiu],ayba

输出

abcd,e%sa,@ert&,,qet|,[;;efeg;sy bh|slhg],oiuy#,[abh;ohg;;a oiu],ayba

我尝试创建 sed 替换命令

echo "abcd,e%sa,@ert&,,qet|,[,,efeg,sy bh|slhg],oiuy#,[abh,ohg;,a oiu],ayba" | sed 's/\[\([^]]*\),\([^[]*\)\]/\[\1;\2\]/g'

输出

abcd,e%sa,@ert&,,qet|,[,,efeg;sy bh|slhg],oiuy#,[abh,ohg;;a oiu],ayba

但它在每个 '[' 和 ']' 之间的子字符串中只替换一次。

我在上面的 sed 命令中犯了什么错误或任何其他方式做同样的事情?

【问题讨论】:

  • 如果输入是[,[],预期的输出是什么?请注意,, 在两个连续的[] 之间。换句话说,如果括号不平衡,输出应该是什么?或者,甚至它们是平衡的,例如[,[]]

标签: perl sed


【解决方案1】:

使用Perl,你可以使用

(?:\G(?!\A)|\[)[^],]*\K,

a demo on regex101.com


Perl 这可能是:

perl -pi.bak -e 's/(?:\G(?!\A)|\[)[^],]*\K,/;/g' test.txt

【讨论】:

  • 我对 perl 脚本没有太多了解。您能详细说明如何将上述表达式与 perl 命令一起使用吗?
【解决方案2】:

我知道你说过你想要 sed 或 perl,但是在 GNU awk 中执行此操作的代码会非常清晰和简单:

$ awk -v RS='[[][^]]+]' '{gsub(/,/,";",RT); printf "%s%s", $0, RT}' file
abcd,e%sa,@ert&,,qet|,[;;efeg;sy bh|slhg],oiuy#,[abh;ohg;;a oiu],ayba

在上面您只需将RS 设置为您要查找的正则表达式([ 然后不是]s 然后]),然后在匹配的字符串中将, 替换为;正则表达式(存储在RT),然后打印结果。不需要神秘的转义序列或单个字符符文的神秘组合。

我希望可以执行此操作的 sed 脚本将是 GNU 特定的,而 perl 是非标准的,因此如果您拥有或可以安装其中任何一个,那么您也应该拥有或能够安装 GNU awk。

【讨论】:

    【解决方案3】:

    修改示例输入,希望我对问题的理解是正确的:

    $ s='a,b,c[,,1,23,4]e,w[6,7,,32]j,g'
    
    $ echo "$s" | sed ':a s/\[\([^]]*\),\([^[]*\)\]/\[\1;\2\]/; ta'
    a,b,c[;;1;23;4]e,w[6;7;;32]j,g
    

    上面的sed 命令是根据问题中提到的命令修改的,​​以使用循环替换所有出现的情况。您可以将其简化为sed -E ':a s/(\[[^]]*),([^[]*])/\1;\2/; ta'

    :a 标记替代命令的标签。仅当替换成功时,ta 才会分支到标签 a。有关文档,请参阅 https://www.gnu.org/software/sed/manual/sed.html#Programming-Commands


    你可以不用循环使用perl

    $ echo "$s" | perl -pe 's/\[[^]]+]/$&=~tr|,|;|r/ge'
    a,b,c[;;1;23;4]e,w[6;7;;32]j,g
    

    e 标志允许在替换部分使用 Perl 代码。这里$&=~tr|,|;|r 将替换,; 仅用于匹配部分($& 类似于sed 中的& - 给出整个匹配部分)

    【讨论】:

    • 感谢您的解决方案。 sed 在我的系统中工作,但不知何故使用 perl 命令我得到以下错误。 $ 回声 "$s" | perl -pe 's/[[^]]+]/$&=~tr|,|;|r/ge' 在 -e 第 1 行,“tr|,|;|r” 语法附近的运算符预期位置找到裸字-e 第 1 行的错误,“tr|,|;|r” 附近 -e 的执行因编译错误而中止。
    • @rohitsoren 不确定该错误,我刚刚再次检查,它对我有用。 perl --version 给我v5.22.1,你的呢?
    • @Sundeep 我的 perl 版本是 v5.8.8。您的 sed 解决方案对我有用。
    • @EdMorton sed 变体 - GNU sed 版本 4.1.5
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多