我有一个看起来像这样的文件:
bar
barfo
barfoo
barfooo
barfoooo
sample
sampleText1
sampleText2
sampleText3
prefix
prefixFooBar
prefixBarFoo
我希望sed(或awk)要做的是从其所有内容中删除引入一个节的字符串,以便最终得到:
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
我尝试使用
sed -e -i '/([[:alpha:]]+)/,/^$/ s/\1//g' file
但是由于“无效的反向引用”而失败。
答案 0 :(得分:5)
$ awk '{$0=substr($0,idx)} !idx{idx=length($0)+1} !NF{idx=0} 1' file
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
答案 1 :(得分:3)
另一个awk
$ awk '{sub(pre,"")}1; !NF{pre=""} !pre{pre=$1}' file
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
答案 2 :(得分:2)
perl -ple'
if (!length($_)) { $re = "" }
elsif (!length($re)) { $re = $_ }
else { s/^\Q$re// }
'
注意:
s/\Q$re//g
删除行中的任何地方,而不仅仅是删除前缀。\
,.
和*
,这也可以使用。答案 3 :(得分:1)
sed解决方案,主要用来说明sed可能不是这样做的最佳选择:
$sed -E '1{h;b};/^$/{n;h;b};G;s/^(.*)(.*)\n\1$/\2/' infile
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
这是它的工作方式:
1 { # on the first line
h # copy pattern buffer to hold buffer
b # skip to end of cycle
}
/^$/ { # if line is empty
n # get next line into pattern buffer
h # copy pattern buffer to hold buffer
b # skip to end of cycle
}
G # append hold buffer to pattern buffer
s/^(.*)(.*)\n\1$/\2/ # substitute
复杂的部分在替换中。替换之前,模式缓冲区保存如下内容:
prefixFooBar\nprefix
现在,替换匹配两个捕获组,第一个捕获组由\n
和字符串结尾之间的内容引用-我们从保持缓冲区中获取的前缀。
然后替换是原始行的其余部分,并且删除了前缀。
备注:
-r
而不是-E
-E
只是为了方便;没有它,替换看起来像
s/^\(.*\)\(.*\)\n\1$/\2/
但仍然可以使用。
对于macOS sed,它可与命令之间的文字换行符一起使用:
sed -E '1{
h
b
}
/^$/{
n
h
b
}
G
s/^(.*)(.*)\n\2$/\2/' infile
答案 4 :(得分:1)
这是另一个sed
解决方案。仅当段落以开头的所有字符串都以主题行开头时,它才有效。
sed -e '1{h;b};/^$/{n;h;b};H;g;s/\(.*\)\n\1//;p;g;s/\n.*//;h;d' file
1
第一行:h
复制以保留空间,b
打印并继续下一行/^$/
空行:n
打印并读取下一行,h
复制以保留空间,b
打印并继续H
追加以换行符容纳空间g
将保留空间复制到模式空间s/\(.*\)\n\1//
从模式空间中删除第一行及其内容,在第二行中p
打印图案空间g
将保留空间复制到模式空间,以便从H
中删除新内容/\n.*//
删除新内容h
复制回保留空间d
删除图案空间 sed
对于这些事情没有用。
由于s
的搜索模式中没有分组,因此您获得“无效的反向引用”。
答案 5 :(得分:1)
另一个awk:
$ awk '{if(p&&match($0,"^" p))$0=substr($0,RLENGTH+1);else p=$0}1' file
输出:
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
答案 6 :(得分:1)
这是另一个awk解决方案:
awk '{gsub(s,"")}1; s==""||!NF{s=$0}' file
优点:
0
/ false
。缺点:
答案 7 :(得分:1)
这可能对您有用(GNU sed):
sed 'G;s/^\(.\+\)\(.*\)\n\1$/\2/;t;s/\n.*//;h' file
将上一个键(如果是第一行,则不添加)添加到当前行。删除键和上一个键(如果它们匹配),打印当前行并重复。否则,密钥不匹配,请删除旧的附加密钥,将新密钥存储在保留空间中并打印新密钥。