如何用 '*' 替换所有中间字符?

4

我希望将单词中间的部分替换为****。

例如:

ifbewofiwfib
wofhwifwbif
iwjfhwi
owfhewifewifewiwei
fejnwfu
fehiw
wfebnueiwbfiefi

Should become :

if********ib
wo*******if
iw***wi
ow**************ei
fe***fu
fe*iw
wf***********fi

到目前为止,我已经成功替换掉了除前两个字符之外的所有内容:

sed -e 's/./*/g3' 

或者您可以走一条更长的路:
grep -o '^..' file > start
cat file | sed 's:^..\(.*\)..$:\1:' | awk -F. '{for (i=1;i<=length($1);i++) a=a"*";$1=a;a=""}1' > stars
grep -o '..$' file > end
paste -d "" start stars > temp
paste -d "" temp end > final

1
你目前进展如何?你被卡在哪了?你具体需要什么? - vincrichaud
到目前为止,我已经成功地使用sed -e 's/./*/g3'替换了除前两个字符以外的所有字符,或者使用grep获取前两个字符和最后两个字符,然后使用sed将其余部分更改为**,最后使用paste将它们粘合在一起。目标是在所有行中用*替换第一个和最后一个字符之间的所有字符。 - MataKiera
4个回答

4
我会使用Awk进行此操作,如果您有GNU Awk,可以将字段分隔符设置为空字符串(如何将字段分隔符设置为空字符串?)。
这样,您可以循环遍历字符并用“*”替换所需的字符。在这种情况下,从第3个到倒数第3个进行替换。
$ awk 'BEGIN{FS=OFS=""}{for (i=3; i<=NF-2; i++) $i="*"} 1' file
if********ib
wo*******if
iw***wi
ow**************ei
fe***fu
fe*iw
wf***********fi

3

您可以通过重复的替换来实现,例如:

sed -E ':a; s/^(..)([*]*)[^*](.*..)$/\1\2*\3/; ta'

解释

这个方法通过一遍又一遍的替换操作直到没有改变为止,也就是:a; ...; ta这一部分的作用。替换操作包括三个匹配的组和一个非星号字符:

  • (..) 字符串的开头。
  • ([*]*) 已经替换过的任意字符。
  • [^*] 下一个需要替换的字符。
  • (.*..) 剩余需要替换的所有字符和字符串的结尾。

GNU sed备选答案

你也可以使用保持空间来实现,可能更易读,例如:

h                                 # save a copy to hold space
s/./*/g3                          # replace all but 2 by *
G                                 # append hold space to pattern space
s/^(..)([*]*)..\n.*(..)$/\1\2\3/  # reformat pattern space

像这样运行它:

sed -Ef parse.sed input.txt

两种情况下的输出结果

if********ib
wo*******if
iw***wi
ow**************ei
fe***fu
fe*iw
wf***********fi

很好,也可以使用(.*..)$代替([^*]*)(..)$ - Sundeep

3
如果 perl 可以使用:
$ perl -pe 's/..\K.*(?=..)/"*" x length($&)/e' ip.txt
if********ib
wo*******if
iw***wi
ow**************ei
fe***fu
fe*iw
wf***********fi
  • ..\K.*(?=..) 用于匹配除去首/尾两个字符以外的其他字符
  • e 修改符允许在替换部分使用Perl代码
  • "*" x length($&) 使用长度函数和字符串重复操作符来获得所需的替换字符串

2
这是一个很好的方法,做得好!这是 Perl 有而我在 Awk 中想念的东西。 - fedorqui

1

以下的 awk 可以帮助你完成相同的任务。它适用于任何版本的 awk

awk '{len=length($0);for(i=3;i<=(len-2);i++){val=val "*"};print substr($0,1,2) val substr($0,len-1);val=""}'  Input_file

现在也添加了一种非单行解决方案。

awk '
{
  len=length($0);
  for(i=3;i<=(len-2);i++){
    val=val "*"};
  print substr($0,1,2) val substr($0,len-1);
  val=""
}
'  Input_file

说明:现在为上述代码添加说明。

awk '
{
  len=length($0);                           ##Creating variable named len whose value is length of current line.
  for(i=3;i<=(len-2);i++){                  ##Starting for loop which starts from i=3 too till len-2 value and doing following:
    val=val "*"};                           ##Creating a variable val whose value is concatenating the value of it within itself.
  print substr($0,1,2) val substr($0,len-1);##Printing substring first 2 chars and variable val and then last 2 chars of the current line.
  val=""                                    ##Nullifying the variable val here, so that old values should be nullified for this variable.
}
' Input_file                                ##Mentioning the Input_file name here.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接