如果有一个文本文件包含以下内容:
1 2 3 4 5 6
如何用空格等字符替换某个字符串(例如 4)之前的所有内容?
1 2 3 4 5 6(输入)
4 5 6 (OUTPUT)
这可能对您有用(GNU sed):
sed '/4/{:a;/^ *4/!s/[^ ]/ /;ta}' file
或者:
sed 's/4/\n&/;T;h;s/[^\n]/ /g;G;s/\n.*\n//' file
或者:
awk '/4/{while(!/^ *4/)sub(/[^ ]/," ")}1' file
或者:
awk '/4/{sub(/4/,"\n&");h=$0;gsub(/[^\n]/," ");$0=$0 h;sub(/\n.*\n/,"")}1' file
你现在真的进入了一些神秘的 sed 魔法。保持简单,只需使用清晰的函数名称、变量和可理解的结构在 awk 中编写:
$ cat file
1 2 3 4 5 6
$ awk 'match($0,/4/){
pre=substr($0,1,RSTART-1)
gsub(/./," ",pre)
print pre substr($0,RSTART)
}' file
4 5 6
sed 是用于在单行上进行简单替换的出色工具,但对于其他任何事情,只需使用 awk。如果您使用超过 s、g 和 p(带 -n)的 sed 语言结构,那么您使用的工具是错误的。一旦 awk 被发明,几乎所有其他 sed 语言结构都在 1976 年左右过时了。
如果您在一年后回来增强此脚本以执行不同的操作,例如在行尾打印一个计数,现在许多字符已替换为空格,您是否愿意尝试理解然后修改它:
sed 's/\(4\)/\n\1/;Tq;h;s/^[^\n]*\n//;x;s/\n.*//;s/./ /g;G;s/\n//;:q'
还是上面的 awk 脚本?在 awk 脚本中进行的调整只是添加和打印一个变量(cnt
如下):
awk 'match($0,/4/){
pre=substr($0,1,RSTART-1)
cnt=gsub(/./," ",pre)
print pre substr($0,RSTART), cnt
}' file
我预计,要让 sed 脚本执行此操作,需要 3 只山羊、一个血月和蝙蝠侠符号。
$ echo -e '1 2 3 4 5 6\n7 8 9 0 1 2'|
> sed 's/4/\n&/;T;h;s/^[^\n]*\n//;x;s/\n.*//;s/./ /g;G;s/\n//'
4 5 6
7 8 9 0 1 2
$
解释:
s/4/\n&/;T # places "\n" marker before "4", quits otherwise
h;s/^[^\n]*\n//;x # puts "4 5 6" into hold space
s/\n.*// # keeps only "1 2 3 "
s/./ /g # replaces each char with space
G;s/\n// # appends "4 5 6" from hold space