如何替换字符串中除某些字符以外的所有字符(在Ruby中)

如何替换字符串中除某些字符以外的所有字符(在Ruby中),ruby,regex,string,Ruby,Regex,String,我在试图找到合适的字符串替换方法时遇到了一些困难。我想替换字符串中的每个字符“除了”一组单词或字符串(在数组中提供)。我知道有一个gsub方法,但我想我想要实现的是它的相反。例如 我的字符串:“需要替换此字符串的一部分” 关键词:[“此字符串”,“已替换”] 所需输出:“*******此字符串*********已替换” 这是我的第一个问题,所以你的帮助将不胜感激 您可以使用以下内容: str="Part of this string needs to be substituted" keep =

我在试图找到合适的字符串替换方法时遇到了一些困难。我想替换字符串中的每个字符“除了”一组单词或字符串(在数组中提供)。我知道有一个
gsub
方法,但我想我想要实现的是它的相反。例如

我的字符串:
“需要替换此字符串的一部分”

关键词:
[“此字符串”,“已替换”]

所需输出:
“*******此字符串*********已替换”


这是我的第一个问题,所以你的帮助将不胜感激

您可以使用以下内容:

str="Part of this string needs to be substituted"
keep = ["this","string", "substituted"]

str.split(" ").map{|word| keep.include?(word) ? word : word.split("").map{|w| "*"}.join}.join(" ")

但这只会保留单词,而不是短语。

这可能比我上一个答案更容易理解:

s = "Part of this string needs to be substituted"
k = ["this string", "substituted"]

tmp = s
for(key in k) {
    tmp = tmp.replace(k[key], function(x){ return "*".repeat(x.length)})
}

res = s.split("")
for(charIdx in s) {
    if(tmp[charIdx] != "*" && tmp[charIdx] != " ") {
        res[charIdx] = "*"
    } else {
        res[charIdx] = s.charAt(charIdx)
    }
}
var finalResult = res.join("")
说明:

这与我之前关于使用关键字所在位置来用星号替换字符串部分的想法不同。首先:

对于每一个关键词,我们都将其替换为与之长度相同的星星。因此:

s.replace("this string", function(x){
    return "*".repeat(x.length)
}
将与“此字符串”匹配的部分替换为x.length
*

我们对每个键都这样做,为了完整性,您应该确保替换是全局的,而不仅仅是找到的第一个匹配项
/this string/g
,我在回答中没有这样做,但我认为您应该能够自己找到如何使用
新RegExp

接下来,我们将原始字符串的副本拆分为一个数组。如果你是一个视觉化的人,将其视为一种奇怪的角色添加应该是有意义的:

"Part of this string needs to be substituted"
"Part of *********** needs to be substituted" +
---------------------------------------------
 **** ** this string ***** ** ** ***********
这就是我们想要的。因此,如果我们的
tmp
变量有星号,那么我们希望带出原始字符串,否则我们希望用
*

使用if语句很容易做到这一点。为了让它像你在问题中的例子一样,我们还引入了原始字符,如果它是一个空格。最后,我们通过
.join(“”
将数组重新连接到字符串中,这样您就可以再次使用字符串了


有意义吗?

这里有一种不同的方法。首先,做与你最终想要的相反的事情:编辑你想要保留的东西。然后逐个字符将这个经过编辑的字符串与原始字符进行比较,如果字符相同,则进行编辑,如果不相同,则保留原始字符

class String
  # Returns a string with all words except those passed in as keepers
  # redacted.
  #
  #      "Part of this string needs to be substituted".gsub_except(["this string", "substituted"], '*')
  #      # => "**** ** this string ***** ** ** substituted"
  def gsub_except keep, mark
    reverse_keep = self.dup
    keep.each_with_object(Hash.new(0)) { |e, a| a[e] = mark * e.length }
             .each { |word, redacted| reverse_keep.gsub! word, redacted }
    reverse_keep.chars.zip(self.chars).map do |redacted, original|
      redacted == original && original != ' ' ?  mark : original
    end.join
  end
end

您可以使用以下方法:收集需要转换为星号的子字符串,然后执行此替换:

str="Part of this string needs to be substituted"
arr = ["this string", "substituted"]

arr_to_remove = str.split(Regexp.new("\\b(?:" + arr.map { |x| Regexp.escape(x) }.join('|') + ")\\b|\\s+")).reject { |s| s.empty? }

arr_to_remove.each do |s|
    str = str.gsub(s, "*" * s.length)
end
puts str
报告的产出:


您可以使用的形式是使用带有捕获组的正则表达式

代码

def sub_some(str, keywords)
  str.split(/(#{keywords.join('|')})/)
     .map {|s| keywords.include?(s) ? s : s.gsub(/./) {|c| (c==' ') ? c : '*'}}
     .join
end
str = "Part of this string needs to be substituted"
keywords = ["this string", "substituted"]
sub_some(str, keywords)
  #=> "**** ** this string ***** ** ** substituted" 
示例

def sub_some(str, keywords)
  str.split(/(#{keywords.join('|')})/)
     .map {|s| keywords.include?(s) ? s : s.gsub(/./) {|c| (c==' ') ? c : '*'}}
     .join
end
str = "Part of this string needs to be substituted"
keywords = ["this string", "substituted"]
sub_some(str, keywords)
  #=> "**** ** this string ***** ** ** substituted" 
解释

r = /(#{keywords.join('|')})/
  #=> /(this string|substituted)/ 
a = str.split(r)
  #=> ["Part of ", "this string", " needs to be ", "substituted"] 
e = a.map
  #=> #<Enumerator: ["Part of ", "this string", " needs to be ",
  #     "substituted"]:map> 

s = e.next
  #=> "Part of " 
keywords.include?(s) ? s : s.gsub(/./) { |c| (c==' ') ? c : '*' }
  #=> s.gsub(/./) { |c| (c==' ') ? c : '*' }
  #=> "Part of "gsub(/./) { |c| (c==' ') ? c : '*' }
  #=> "**** ** " 

s = e.next
keywords.include?(s) ? s : s.gsub(/./) { |c| (c==' ') ? c : '*' }
  #=> "this string" 
keywords.include?(s) ? s : s.gsub(/./) { |c| (c==' ') ? c : '*' }
  #=> s
  #=> "this string" 
请注意,在v.1.9.3之前的版本中,未给出块时,未返回枚举数。然而,计算结果是相同的

str = "Part of this string needs to be substituted"
keywords = ["this string", "substituted"]

pattern = /(#{keywords.join('|')})/

str.split(pattern).map {|i| keywords.include?(i) ? i : i.gsub(/\S/,"*")}.join
#=> "**** ** this string ***** ** ** substituted"
同一代码的可读性更强的版本

str = "Part of this string needs to be substituted"
keywords = ["this string", "substituted"]

#Use regexp pattern to split string around keywords.
pattern = /(#{keywords.join('|')})/ #pattern => /(this string|substituted)/
str = str.split(pattern) #=> ["Part of ", "this string", " needs to be ", "substituted"]

redacted = str.map do |i|
    if keywords.include?(i)
        i
    else
        i.gsub(/\S/,"*") # replace all non-whitespace characters with "*"
    end
end      
# redacted => ["**** **", "this string", "***** ** **", "substituted"]
redacted.join

你可以找到你的关键字的
索引,然后在非关键字的地方填上星号,除非是空格啊,OP最初问的问题不是Ruby,我只是假设javascript。这个可能会对他们有更多帮助+1非常感谢您!到目前为止,这对我来说是有效的——我正在尝试为正则表达式添加更多的条件,我会看看这是怎么回事!