【问题标题】:Translate regex substitution from RegEXR to work in bash script将 RegEXR 中的正则表达式替换转换为在 bash 脚本中工作
【发布时间】:2014-04-11 13:56:26
【问题描述】:

我正在尝试在 bash 脚本中创建一个正则表达式替换命令,但是在使用了单引号、双引号和转义字符之后,我的头发被拉了出来。我使用 RegEXR 来组合模式,并得出以下结论:

我搜索:

/\.icon-(.*) {\n\t/gm

并希望将其替换为:

if(strpos(\$embedicons,'$1') !== false) { \$svgicons .= <<<'EOD'\n\.$1 {

这取代了这个:

.icon-basket-14-icon {
    background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
    background-repeat: no-repeat;
}

用这个:

if(strpos($embedicons,'basket-14-icon') !== false) { $svgicons .= <<<'EOD'
.basket-14-icon {background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
    background-repeat: no-repeat;
}

但是,我无法在 bash 脚本中实现它。我不确定它是否相关,但我在 OSX Mavericks 并使用终端应用程序。虽然 RegExr 中的模式对我来说很有意义,但一旦我开始逃避它,我就完全不知道发生了什么。

  1. 如何确保正则表达式是全局的和多行的?
  2. 使用其他选项是否比内置正则表达式更好?
  3. 是否有在线资源可以教 (bash) 正则表达式来完成新手?
  4. 是否存在匹配所有内容(包括空格和 换行符)直到给定的字符链,如星号 (*)?

显然我不是在寻找讲义,因为这个问题经常困扰我......我很想学习正则表达式并通过学习来解决我的问题,我在网上研究了一些例子,但它们似乎太先进了。也许有一个像 RegExr 这样的在线生成器,可以翻译成 bash 兼容和 PHP 兼容的正则表达式模式版本?


更新/解决方案:

以下似乎在 OSX Mavericks 终端中对我有用:

sed "s|\.icon-\(.*\) {|if(strpos(\$embedicons,'\1') !== false) { \$svgicons \.= <<<'EOD' \.\1 {|g"

【问题讨论】:

    标签: regex bash global osx-mavericks multiline


    【解决方案1】:

    我建议使用sed 进行这种替换,这条线会做你想要的:

    sed "s/^.icon-\(.*\) {$/if(strpos(\$embedicons,'\1') !== false) { \$svgicons .= <<<'EOD'\n.\1 {/"g input_file.txt
    

    input_file.txt:

    .icon-basket-14-icon {
        background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
        background-repeat: no-repeat;
    }
    

    输出:

    if(strpos($embedicons,'basket-14-icon') !== false) { $svgicons .= <<<'EOD'
    .basket-14-icon {
        background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
        background-repeat: no-repeat;
    }
    

    设置-r(扩展正则表达式)标志后,您只需在示例中转义大括号和变量美元符号。

    关于您的问题:

    • sedg 标志使其全局化。 “多行”到底是什么意思?使用 \n 输出换行符很容易,跨行匹配有点复杂,因为sed 逐行操作。一种常见的技术是用占位符替换文件/数据中的所有换行符,在执行正则表达式/替换时记住占位符,然后再次用换行符替换占位符。
    • sed 可能是你最好的正则表达式类型的东西。你可以在网上找到文档,这是相当全面的:http://www.grymoire.com/Unix/Sed.html

    对于最后一部分,使用 (.*) 将捕获所有内容,然后您只需处理换行符并确保正确转义终止字符串。

    测试文件:

    testing data with space -
    and newlines /'\ *** ends
    there
    

    命令(tr 正在将换行符换成波浪线并再次返回):

    tr '\n' '~' < testfile | sed -r 's/(.*)\*\*\*.*/\1/g' | tr '~' '\n'
    

    输出:

    testing data with space -
    and newlines /'\ 
    

    【讨论】:

    • 感谢乔希,您的回复。我正在尝试立即对其进行测试。看来我的 sed 版本(在 OSX Mavericks 上)不喜欢 -r 选项。删除后,请参阅抱怨: sed: 1: "s/^.icon-(.*) \{$/if(st ...": RE 错误:无效的重复计数我会玩一点,然后努力让它发挥作用。非常感谢您的长篇回复和所有提示。每一点知识对我来说都是一个里程碑。
    • 您可以删除 -r 标志,然后您必须转义语法大括号和括号。我现在不能测试,但会编辑。如果你不能让它工作,稍后会回来!
    • 所以,在你的帮助下,我设法到达了某个地方。我不确定这看起来有多业余,但这对我现在有用:sed "s|\.icon-\(.*\) {|if(strpos(\$embedicons,'\1') !== false) { \$svgicons \.= &lt;&lt;&lt;'EOD' \.\1 {|g" 我不得不将 sed 中的 \ 替换为 |否则栅栏让我的大脑麻木了。我放弃了更换换行符。我现在明白 tr 需要相同长度的字符串,我担心代字号 (~) 有一天会出现在代码中的某个地方并把它搞砸。如果我可以用长字符串替换换行符,然后在 sed 完成后返回,那就太好了。
    • 您可以再次使用 sed 代替 tr,只是一个更长的命令并且可能更昂贵:sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/PLACEHOLDERSTRING/g' 删除换行符,sed -e ':a' -e 'N' -e '$!ba' -e 's/PLACEHOLDERSTRING/\n/g' 替换它们。
    猜你喜欢
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    相关资源
    最近更新 更多