假设我有一个包含字母Z的多个出现的字符串。
例如:aaZbbZccZ
。
我希望每次打印该字符串的部分内容,直到下一次出现Z:
aaZ
aaZbbZ
aaZbbZccZ
所以我尝试使用unix sed,使用命令sed s/Z.*/Z/i
,其中i是一个索引,我从1运行到字符串中的Z的数量。就我的理解而言:这应该删除在第一个Z之后出现的所有内容,但实际上这只有当我在sed s/Z.*/Z/
中有i = 1时才有效,但不是因为我增加了i,例如,在sed s/Z.*/Z/2
中,它只打印整个原始字符串。感觉好像有关于sed功能的遗漏,因为根据多个手册,它应该有效。
编辑:例如,在应用aaZbbZccZ
时在字符串sed s/Z.*/Z/2
中我希望有aaZbbZ
,因为Z的第二次出现后的所有内容都会被删除。< / p>
答案 0 :(得分:2)
下面的sed与你正在寻找的东西紧密相关,除了它也删除了最后的Z。
$echo aaZbbZccZdd | sed -e 's/Z[^Z]*//1g;s/$/Z/'
aaZ
$echo aaZbbZccZdd | sed -e 's/Z[^Z]*//2g;s/$/Z/'
aaZbbZ
$echo aaZbbZccZdd | sed -e 's/Z[^Z]*//3g;s/$/Z/'
aaZbbZccZ
$echo aaZbbZccZdd | sed -e 's/Z[^Z]*//4g;s/$/Z/'
aaZbbZccZddZ
编辑: 根据亚伦的建议修改。
EDIT2:
如果您不知道字符串中有多少Z,那么在命令下方使用它会更安全。否则在末尾添加额外的Z.
-r
- 启用正则表达式
-e
- 将sed
次操作分开,与;
相同,但在我看来更容易阅读。
$echo aaZbbZccZddZ | sed -r -e 's/Z[^Z]*//1g' -e 's/([^Z])$/\1Z/'
aaZ
$echo aaZbbZccZddZ | sed -r -e 's/Z[^Z]*//2g' -e 's/([^Z])$/\1Z/'
aaZbbZ
$echo aaZbbZccZddZ | sed -r -e 's/Z[^Z]*//3g' -e 's/([^Z])$/\1Z/'
aaZbbZccZ
$echo aaZbbZccZddZ | sed -r -e 's/Z[^Z]*//4g' -e 's/([^Z])$/\1Z/'
aaZbbZccZddZ
$echo aaZbbZccZddZ | sed -r -e 's/Z[^Z]*//5g' -e 's/([^Z])$/\1Z/'
aaZbbZccZddZ
答案 1 :(得分:0)
除非您的字符串可以包含换行符,否则这应该符合您的预期(请参阅注释):
# -n will prevent default printing
echo 'aaZbbZccZ' | sed -n '{
# Add a line break after each 'Z'
s/Z/Z\
/g
# Print it and consume it in the next sed command
p
}' | sed -n '{
# Add only the first line to the hold buffer (you can remove it if you don't mind to see first blank line)
1 {
h
}
# As for the rest of the lines
2,$ {
# Replace the hold buffer with the pattern space
x
# Remove line breaks
s/\n//
# Print the result
p
# Get the hold buffer again (matched line)
x
# And append it with new line to the hold buffer
H
}'
我们的想法是将字符串分解为多个行(每个行以Z
结尾),将在第二个sed
命令上逐个处理。
在第二个sed
上,我们使用Hold Buffer来记住上一行,打印汇总结果,添加新行,每次删除我们之前添加的换行符。
输出
aaZ
aaZbbZ
aaZbbZccZ
答案 2 :(得分:0)
这可能适合你(GNU sed):
sed -n 's/Z/&\n/g;:a;/\n/P;s/\n\(.*Z\)/\1/;ta' file
使用sed的类似grep的选项-n
来明确打印内容。在每个Z
之后附加换行符。如果没有替代品那么就没有什么可做的。打印到第一个换行符,如果以下字符包含Z
,则删除第一个换行符并重复。