SED 挑战,聚合包含大括号的字符串

SED 挑战,聚合包含大括号的字符串

我一直在尝试使用 sed 聚合文本中的特定字符串模式几个小时,但找不到解决方案。我希望你们知道该怎么做!?

  • 我的目标的文本仅由字符串字符组成(不存在不可见的 \t )。
  • 我想找到包含 (TAB) 的字符串部分,但至少有两个彼此相邻,最多 8 个彼此相邻,并将它们替换为单个 (TAB) 条目。

  • 搜索应在包含 bash 脚本的 Shell 文件中执行

例子:

#!/bin/bash

text="Column One(TAB)(TAB)(TAB)Column Two(TAB)(TAB)Column three(TAB)Column4"

modText=`echo $text | sed 's/([(]\{1\}TAB[)]\{1\})\{2,8\}/(TAB)/g'`
  • 我尝试了多个版本的 sed-command,上面的只是其中之一。我最初的想法是 modText=`echo $text | sed 's/\(TAB\)\{1\})\{2,8\}/(TAB)/g'`

如果你能帮助我,那就太好了。感觉解决方案并不遥远,但只是没有更多的想法,而且我的研究没有做到这一点:-S


文本示例

“第一列(TAB)(TAB)(TAB)第二列(TAB)(TAB)第三列(TAB)第四列”

我的搜索条件将与出现在“第一列”和“第三列”之间的前两个 (TAB) 组相匹配。

结果应如下所示:

“第一列(TAB)第二列(TAB)第三列(TAB)第四列”

答案1

我不确定我是否理解“最大 8”条款应该如何应用,但天真的方法是这样的:

sed 's/\((TAB)\)\{2,8\}/(TAB)/g'

答案2

如果你的意思是如果有超过 8 个相邻的 s 则不应进行替换(TAB),你可以这样做:

sed '
   s/_/_u/g; # escape _
   s/|/_p/g; # escape |
   s/(TAB)/|/g; # use a single character in place of (TAB)
   s/.*/<&>/; # add leading and trailing non-| character
   s/\([^|]\)|\{2,8\}\([^|]\)/\1|\2/; # replace up to 8 | provided
                                      # they are not preceded nor followed
                                      # by |
   s/.\(.*\)./\1/; # undo wrapping
   s/|/(TAB)/g;    # undo replacement
   s/_p/|/g;s/_u/_/g; # undo escaping'

如果您的sed(like ssed) 支持类似 perl 的正则表达式,您可以使用环视运算符:

ssed -R 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'

或者perl直接使用:

perl -lpe 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'

AT&T (ast-open) sed,带有-A/-X选项支持一种他们称之为扩展正则表达式增强的有一个否定运算符 ( x!) 和连词操作员 (x&y)。在那里,(.{5}&(\(TAB\))!)匹配 5 个字符的序列,即不是 (TAB)。因此sed,您可以执行以下操作:

sed -A '
  :1
    s/(^.{0,4}|.{5}&(\(TAB\))!)(\(TAB\)){2,8}(.{0,4}$|.{5}&(\(TAB\))!)/\1(TAB)\4/
  t1'

相关内容