【问题标题】:How to replace a substring based on index?如何根据索引替换子字符串?
【发布时间】:2016-08-28 03:08:23
【问题描述】:

我有一个字符串(实际上是一个日志行,包含敏感信息 (info) ),我想根据字符串中子字符串的索引替换其中的子字符串。子字符串中可以有多个单词,但根据要求必须将其视为单个子字符串。

详情:

所以,这是我的字符串:

[2016-04-25 03:48:34] 123737 error 150531221446 2000 Master dmart 843212 "Tough times"

这里我们需要用一些字符串替换“艰难时期”这个词,比如“人类”。下面是必须处理字符串的方式:

[2016-04-25 03:48:34] -> 索引 0

123737 -> 索引 1

错误 -> 索引 2(...等等)

“艰难时期”-> 索引 8

现在,python 程序(我正在研究)不会对子字符串有任何线索,即“艰难时期”,它只会提供数字“9”(单词的索引,如如上所示),程序将用结果字符串替换第 9 个索引中的任何子字符串。同样,如果程序提供了数字“7”,它将用结果字符串替换第 7 个索引中的任何子字符串。

现在,我尝试使用正则表达式、sed、awk 等,但找不到任何合适的答案。我找到的最接近的解决方案是regex

但它不符合我的要求。

现在,我怀疑我的要求是否荒谬。

【问题讨论】:

  • 所以字符串的每个“子字符串”都用圆括号或方括号括起来,但可能包含多个单词?
  • (信息)的格式是什么?有没有一种我们可以利用的模式来索引事物?每个字段之间的分隔符?
  • 所以为了澄清,通过索引,您实际上并不是指 python 字符串索引。如果是这样,那么您是在问我们如何按照您概述的方式对字符串进行分组、拆分和计数。如果不知道(info) 的样子,这将是一件很难回答的事情。你最好的选择是想出一个正则表达式来分隔所有单独的“子字符串”,并使用 re.split。
  • 您可以使用 (?<=]|)|\") (?=(|[|\") 进行拆分,但它不会关心平衡组或在三个选项上使用简单捕获
  • @ByteCommander :不,除了日期时间部分 [2016-04-25 03:48:34] 之外,子字符串不被圆括号或方括号括起来,我使用了模式“(信息)”使人们了解日志行的结构。无论如何,编辑我的问题以便更好地理解。

标签: python regex string awk sed


【解决方案1】:

您可以对上述内容使用简单的字符串拆分操作:

string= '[2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) "Tough times"'
a=(string.split('] ')[0]+']')
words=((string.split('] ')[1]).split(' ',7))
words.insert(0,a)

现在您可以通过索引值访问单词。对于连接,您可以使用:

words[8]='changed string'
new_string=' '.join(words)

输出将是:

'[2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) changed string'

【讨论】:

    【解决方案2】:

    这是可用于查找由圆括号、方括号、单引号或双引号分隔的所有子字符串的正则表达式:

    (?:([\"\'])|(\()|(\[)).+?(?(1)\1|(?(2)\)|\]))
    

    Check this regex out at regex101.com

    这是一个用法示例:

    import re
    regex = re.compile(r'(?:([\"\'])|(\()|(\[)).+?(?(1)\1|(?(2)\)|\]))')
    
    line = '[2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) "Tough times"'
    index = 9  # 1-based index
    replacement = '"Human race"'  # note the double quotes that will appear in the result
    
    substrings = [match.group(0) for match in regex.finditer(s)]
    item_to_replace = substrings[index-1]
    
    result = line.replace(item_to_replace, replacement)
    print(result)
    

    输出:

    [2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) "Human race"
    

    【讨论】:

      【解决方案3】:

      修改问题的答案

      让我们从字符串开始:

      >>> orig = '[2016-04-25 03:48:34] 123737 error 150531221446 2000 Master dmart 843212 "Tough times"'
      

      接下来,让我们将字符串分成子字符串:

      >>> import re
      >>> s = re.findall(r'(\[[^]]*\]|\w+|"[^"]*")', orig)
      >>> s
      ['[2016-04-25 03:48:34]', '123737', 'error', '150531221446', '2000', 'Master', 'dmart', '843212', '"Tough times"']
      

      现在,让我们更改第九个子字符串并重新组合字符串:

      >>> s[8] = '"Human race"'
      >>> ' '.join(s)
      '[2016-04-25 03:48:34] 123737 error 150531221446 2000 Master dmart 843212 "Human race"'
      

      更多关于正则表达式

      正则表达式允许子字符串匹配以下三种模式中的任何一种:

      1. \[[^]]*\]:以[ 开头并以] 结尾的子字符串,其间包含除] 之外的任何字符。

      2. \w+: 任意一系列“单词”字符。

      3. "[^"]*":双引号字符串。

      原始问题的答案

      这种方法在字符串中寻找匹配的分隔符。分隔符可以是 (a) [],或 (b) (),或 (c) ""。分隔符可以按任何顺序出现。一旦找到匹配的分隔符,字符串就会被分成子字符串,然后我们可以对其进行更改和重新组合。

      为了演示,让我们从这个字符串开始:

      >>> orig = '[2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) "Tough times"'
      

      接下来,让我们用匹配的分隔符将其分成几组:

      >>> import re
      >>> s = re.findall(r'(\[[^]]*\]|\([^)]*\)|"[^"]*")', orig)
      >>> s
      ['[2016-04-25 03:48:34]', '(info)', '(info)', '(info)', '(info)', '(info)', '(info)', '(info)', '"Tough times"']
      

      现在,让我们更改第九个字符串并重新组合:

      >>> s[8]='"Human Race"'
      >>> ' '.join(s)
      '[2016-04-25 03:48:34] (info) (info) (info) (info) (info) (info) (info) "Human Race"'
      

      【讨论】:

      • 所有答案都会出错,因为 OP 已经修改了问题(在 cmets 中)
      【解决方案4】:

      看起来你有一个列表

      只需按其索引处理列表即可:

      l=["2016-04-25 03:48:34", "info", "info", "info", "info", "info", "info", "info", "Tough times"]
      
      l[8]
      'Tough times'
      

      列表从0开始编号,所以第一个元素是l[0],第九个元素是l[8]

      【讨论】:

      • 输入的是字符串,不是列表。您必须先拆分字符串。
      • 如果输入的是字符串,应该用引号括起来
      • @Louis : 输入是一个字符串,我已经提到过,它在 Details 部分的第一行。
      • 如果我们拆分字符串,“Tought”和“times”就会分开。
      • @niladri chakrabarty : 如果是字符串,用引号显示。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-22
      • 2018-01-09
      • 2019-11-08
      • 2016-03-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      相关资源
      最近更新 更多