【问题标题】:Remove a specific part of string split by multiple-charater delimiter in bash在bash中删除由多字符分隔符分割的字符串的特定部分
【发布时间】:2020-09-24 13:45:46
【问题描述】:

我正在尝试按如下方式处理我的字符串和步骤:

mytext='\\[[123 one (/)\n\\[[456 two (/)\n\\[[789 three (/)'
myvar=456

并且我想在被分隔符\n分割后删除匹配myvar的部分字符串(和分隔符),结果应该是

\\[[123 one (/)\n\\[[789 three (/)

但我还是没有找到解决办法。

如果分隔符是像:这样的单个字符,我可以用sed命令完成:

mytext2='\\[[123 one (/):\\[[456 two (/):\\[[789 three (/)'
myvar2=456
echo $mytext2 | sed -E "s/[^:]*${myvar}[^:]*(:|$)//g"

Result as expected: \\[[123 one (/):\\[[789 three (/)

在这种情况下,如果 delimiter 是多字符怎么办? 谢谢。

【问题讨论】:

  • 请编辑您的 Q 以包含 $mytext 的版本,其中包含所需的 \n 字符以及通过运行您的 cmd 的输出。也可以试试 echo -e "$mytext" | ... 。祝你好运。

标签: regex string bash


【解决方案1】:

即使您使用sed -E,您仍然缺乏一些支持(?<=?!?=? 等)。我建议你使用perl(Perl 兼容的正则表达式)。

mytext='\\[[123 one (/)\n\\[[456 two (/)\n\\[[789 three (/)';
myvar=456;
echo $mytext | perl -pe "s/(?<=\\\n).*${myvar}.*?(\\\n|$)//g";

详情

  • (?&lt;=\\\n):字符串在\n 之后开始。 \\ 转义字符 \
  • .*${myvar}.*?(\\\n|$):获取包含变量myvar的值并以\nend of line结尾的字符串。

结果。

\\[[123 one (/)\n\\[[789 three (/)

【讨论】:

    【解决方案2】:

    如果您能找到另一个分隔符,例如:,您可以先将其替换为:

    echo $mytext | tr '\n' ':' | sed -E "s/[^:]*${myvar}[^:]*(:|$)//g"
    

    完整的脚本如下所示

    mytext='\\[[123 one (/):\\[[456 two (/):\\[[789 three (/)'
    myvar=456
    v=$(echo $mytext | tr '\n' ':' | sed -E "s/[^:]*${myvar}[^:]*(:|$)//g")
    echo $v
    

    如果多字符分隔符类似于abcd,您可以尝试先使用sed 替换它,而不是使用tr

    【讨论】:

      【解决方案3】:

      我建议在这种情况下使用awk,因为您可以将文字多字符分隔符模式指定为输入/输出字段分隔符,遍历字段并丢弃所有与您的值不匹配的字段:

      mytext='\\[[123 one (/)\n\\[[456 two (/)\n\\[[789 three (/)'
      myvar=456
      awk -v myvar=$myvar 'BEGIN{FS=OFS="\\\\n"} {s="";
          for (i=1; i<=NF; i++) { 
              if ($i !~ myvar) {s = s (i==1 ? "" : OFS) $i;}
          }
      } END{print s}' <<< "$mytext"
      # => \\[[123 one (/)\\n\\[[789 three (/)
      

      请参阅online awk demo

      注意事项

      • BEGIN{FS=OFS="\\\\n"} - 将输入/输出字段分隔符设置为 \n
      • -v myvar=$myvarmyvar 传递给 awk
      • s="" - 将 s 分配给一个空字符串
      • for (i=1; i&lt;=NF; i++) {...} - 遍历所有字段
      • if ($i !~ myvar) {...} - 如果当前字段值匹配 myvar...
      • s = s (i==1 ? "" : OFS) $i;} - 将当前字段值附加到s(如果是第一个字段)或输出分隔符和当前字段值(如果不是第一个)
      • END{print s} - 字段检查后打印s

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 2013-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多