[英]Remove leading and trailing numbers from string, while leaving 2 numbers, using sed or awk
[英]Using sed/awk to remove string from subsections
我有一个看起来像这样的文件:
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
但是,“无效的反向引用”失败了。
$ 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
另一个awk
$ awk '{sub(pre,"")}1; !NF{pre=""} !pre{pre=$1}' file
bar
fo
foo
fooo
foooo
sample
Text1
Text2
Text3
prefix
FooBar
BarFoo
perl -ple'
if (!length($_)) { $re = "" }
elsif (!length($re)) { $re = $_ }
else { s/^\Q$re// }
'
笔记:
s/\\Q$re//g
删除行中的任何位置,而不是仅删除前缀。 \\
, .
和*
。 一个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
这是另一个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
的搜索模式中没有组。
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
这是另一个awk解决方案:
awk '{gsub(s,"")}1; s==""||!NF{s=$0}' file
优点:
0
/ false
。 缺点:
这可能适合你(GNU sed):
sed 'G;s/^\(.\+\)\(.*\)\n\1$/\2/;t;s/\n.*//;h' file
将前一个键(如果它是第一行,则没有任何内容)附加到当前行。 如果它们匹配,则移除键和上一个键,打印当前行并重复。 否则密钥不匹配,删除旧的附加密钥,将新密钥存储在保留空间中并打印新密钥。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.