gpt4 book ai didi

sed 配方 : how to do stuff between two patterns that can be either on one line or on two lines?

转载 作者:行者123 更新时间:2023-12-04 19:29:04 25 4
gpt4 key购买 nike

假设我们只想在某些模式之间进行一些替换,让它们成为 <a></a>为清楚起见...(好吧,好吧,它们是 startend !.. Jeez!)

所以我知道如果 start 该怎么办和 end总是出现在同一行:只需设计一个合适的正则表达式即可。

如果保证它们在不同的行上并且我不关心包含 end 的行中的任何内容,我也知道该怎么做我也可以在包含 start 的行中应用所有命令之前 start : 只需将地址范围指定为 /start/,/end/ .

然而,这听起来不是很有用。如果我需要做一个更聪明的工作,例如,在 {...} 中引入变化怎么办?阻止?

我能想到的一件事是打破 { 上的输入和 }在处理和之后将其放回原处之前:

sed 's/{\|}/\n/g' input | sed 'main stuff' | sed ':a $!{N;ba}; s/\n\(}\|{\)\n/\1/g'

另一种选择是相反的:

cat input | tr '\n' '#' | sed 'whatever; s/#/\n/g'

这两个都很丑陋,主要是因为操作不局限于单个命令。第二个更糟糕,因为必须使用某些字符或子字符串作为“换行符”,假设它不存在于原始文本中。

那么问题来了:有没有更好的方法或者上面说的可以优化?从我最近阅读的 SO 问题来看,这是一项非常常规的任务,因此我想一劳永逸地选择最佳实践。

附言我最感兴趣的是纯 sed解决方案:是否可以通过一次调用 sed 来完成这项工作?没有别的吗?请不要 awk , Perl等:这更像是一个理论问题,而不是“需要尽快完成工作”的问题。

最佳答案

这可能对你有用:

# create multiline test data
cat <<\! >/tmp/a
> this
> this { this needs
> changing to
> that } that
> that
> !
sed '/{/!b;:a;/}/!{$q;N;ba};h;s/[^{]*{//;s/}.*//;s/this\|that/\U&/g;x;G;s/{[^}]*}\([^\n]*\)\n\(.*\)/{\2}\1/' /tmp/a
this
this { THIS needs
changing to
THAT } that
that
# convert multiline test data to a single line
tr '\n' ' ' </tmp/a >/tmp/b
sed '/{/!b;:a;/}/!{$q;N;ba};h;s/[^{]*{//;s/}.*//;s/this\|that/\U&/g;x;G;s/{[^}]*}\([^\n]*\)\n\(.*\)/{\2}\1/' /tmp/b
this this { THIS needs changing to THAT } that that

解释:

  • 将数据读入模式空间(PS)。 /{/!b;:a;/}/!{$q;N;ba}
  • 将数据复制到保留空间 (HS)。 h
  • 从字符串的前后剥离非数据。 s/[^{]*{//;s/}.*//
  • 转换数据,例如s/this\|that/\U&/g
  • 交换到 HS 并附加转换后的数据。 x;G
  • 用转换后的数据替换旧数据。s/{[^}]*}\([^\n]*\)\n\(.*\)/{\2}\1/

编辑:

一个更复杂的答案,我认为它可以满足每行不止一个 block 的需要。

# slurp file into pattern space (PS)
:a
$! {
N
ba
}
# check for presence of \v if so quit with exit value 1
/\v/q1
# replace original newlines with \v's
y/\n/\v/
# append a newline to PS as a delimiter
G
# copy PS to hold space (HS)
h
# starting from right to left delete everything but blocks
:b
s/\(.*\)\({.*}\).*\n/\1\n\2/
tb
# delete any non-block details form the start of the file
s/.*\n//
# PS contains only block details
# do any block processing here e.g. uppercase this and that
s/th\(is\|at\)/\U&/g
# append ps to hs
H
# swap to HS
x
# replace each original block with its processed one from right to left
:c
s/\(.*\){.*}\(.*\)\n\n\(.*\)\({.*}\)/\1\n\n\4\2\3/
tc
# delete newlines
s/\n//g
# restore original newlines
y/\v/\n/
# done!

注意这使用 GNU 特定选项,但可以进行调整以与通用 sed 一起使用。

关于sed 配方 : how to do stuff between two patterns that can be either on one line or on two lines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11024245/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com