我有两种模式START
和END
,想用这些模式之间的下划线替换每个空格。
示例
Lorem ipsum dolor START sit amet, consectetur END adipiscing elit.
应转换为
Lorem ipsum dolor START_sit_amet,_consectetur_END adipiscing elit.
我知道用下划线替换每个空格的正则表达式
sed 's/ /_/g'
我也知道如何匹配两种模式之间的部分
sed 's/.*START\(.*\)END.*/\1/g'
但是我不知道如何将这两件事结合起来。
答案 0 :(得分:2)
您也可以使用Perl:
perl -pe 's/(START.*?END)/$1=~s#\s#_#gr/ge'
(START.*?END)
模式匹配START
和END
之间的子字符串,同时将其捕获到组1中,然后s#\s#_#gr
将每个单个空格(\s
)替换为_
在该组的内容中。
或者,如果您使用的Perl不支持r
选项:
perl -pe 's/(?:START|\G(?!^))(?:(?!END).)*?\K\s/_/g'
请参见online demo和second regex demo online。
(?:START|\G(?!^))(?:(?!END).)*?\K\s
匹配
(?:START|\G(?!^))
-START
子字符串或上一个成功匹配的结尾(与\G(?!^)
一起结束)(?:(?!END).)*?
-除换行符以外的任何字符,不以END
子字符串开头,应尽可能少\K
-匹配重置运算符,丢弃先前匹配的文本\s
-空格字符。答案 1 :(得分:1)
您可以使用此awk
来完成工作:
awk -v ts='START ' -v te='END ' '{
while (n = index($0, ts)) {
m = index($0, te)
if (m > n) {
s = substr($0, n, m-n)
gsub(/[[:blank:]]+/, "_", s)
$0 = substr($0, 1, n-1) s substr($0, m)
}
}
} 1' file
Lorem ipsum dolor START_sit_amet,_consectetur_END adipiscing elit.
答案 2 :(得分:1)
使用GNU awk:
import json
chunk_size = 1024
with open('file.txt', 'rb+') as f:
f.seek(-chunk_size, 2)
buffer = ''
while True:
fragments = f.read(chunk_size).decode().split('{')
f.seek(-chunk_size * 2, 1)
i = len(fragments)
for fragment in fragments[:0:-1]:
i -= 1
buffer = '{%s%s' % (fragment, buffer)
try:
json.loads(buffer)
break
except ValueError:
pass
else:
buffer = fragments[0] + buffer
continue
break
next_fragment = fragments[i - 1]
# if we don't have a comma in the preceding fragment and it is already the first
# fragment, we need to read backwards a little more
if i == 1 and ',' not in fragments[0]:
f.seek(-2, 1)
next_fragment = f.read(2).decode() + next_fragment
buffer = next_fragment[next_fragment.rindex(','):] + buffer
f.seek(-len(buffer.encode()), 2)
f.truncate()
这取决于将记录分隔符awk -v RS='(START|END)' 'RT=="END"{gsub(" ","_")}{printf "%s%s",$0,RT}' file
设置为RS
或START
。
如果到达END
标记,则会使用功能END
更新记录以用下划线替换空格。
最后一条语句打印整个记录,包括记录终止符gsub()
(与RT
匹配)。
请注意,此解决方案允许RS
和START
跨越不同的行(并且必须在同一行)。