我一直在尝试使用 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'