在列表元素中查找并替换符号

huangapple go评论109阅读模式
英文:

Finding and replacing symbols in list elements

问题

需要处理环境变量中的 % 符号,将其替换为 ${} 形式。代码中的相关部分如下:

  1. # Pattern to recognize when performing the Folder Exceptions
  2. var_pattern = re.compile(r"%([^%]+)%")
  3. # Function to swap out the '%' symbols in environment variables
  4. def process_var_sub(match):
  5. var_name = match.group(1)
  6. return "${" + var_name.lower() + "}"
  7. # Function to write Folder Exceptions
  8. def write_folder_exception_list(excluded_folder_list, policy_name, section):
  9. if len(excluded_folder_list):
  10. for i in range(len(excluded_folder_list)):
  11. excluded_folder_list_cleaned = [
  12. var_pattern.sub(process_var_sub, p)
  13. for p in excluded_folder_list
  14. ]
  15. excluded_folder_list = excluded_folder_list_cleaned
  16. excluded_folder_list[i] = excluded_folder_list[i] + "\\"
  17. excluded_folder_list = {
  18. 'name': policy_name + " " + section + " Exclusions",
  19. 'description': "",
  20. 'items': excluded_folder_list_cleaned
  21. }
  22. payload = json.dumps(excluded_folder_list, indent=4)
  23. print(payload)
  24. url = baseurl + "directorylists"
  25. response = requests.request("POST", url, headers=headers, data=payload)
  26. print(response.text)
  27. del response
  28. del url
  29. del excluded_folder_list
  30. del payload
  31. else:
  32. return

以上就是对环境变量中 % 符号进行替换的代码部分。

英文:

I need to take a list of items (that list is not static and will change every time the script is run) that may or may not have multiple certain symbols in the list elements, for example:

  1. a = ['C:\\Temp\\Folder1',
  2. 'C:\\Temp\\Folder2',
  3. 'C:\\Temp\\Folder3',
  4. 'C:\\Temp\\Folder4',
  5. '%ALLUSERSPROFILE%\\Temp',
  6. '%WINDIR%\\Temp']

and I need to change the item that would have the % symbol to output the following:

  1. a = ['C:\\Temp\\Folder1',
  2. 'C:\\Temp\\Folder2',
  3. 'C:\\Temp\\Folder3',
  4. 'C:\\Temp\\Folder4',
  5. '${allusersprofile}\\Temp',
  6. '${windir}\\Temp']

There could be more than one entry in the list as well so I need to make sure I hit every one that may exist. I've been wracking my brain trying to come up with something and looked at match-case, if/elif/else, and the suggestions are elegant but I'm not sure how to code something like this as it's not a simple 1:1 replacement. Any help is appreciated.

EDIT:

I've tried adding @shadowtalkers code to mine but can't get the desired output. I'm sure I'm missing something innocuous, but I don't know what. The last part of "for" where I'm adding the double-slash, is for API requirements and folder names. Here's a snippet of my current code:

  1. # importing the module
  2. import requests, json, os, re
  3. # Pattern to recognize when preforming the Folder Exceptions
  4. var_pattern = re.compile(r"%([^%]+)%")
  5. # Function to swap out the '%' symbols in environment variables
  6. def process_var_sub(match):
  7. var_name = match.group(1)
  8. return "${" + var_name.lower() + "}"
  9. # Function to write Folder Exceptions
  10. def write_folder_exception_list(excluded_folder_list, policy_name, section):
  11. if len(excluded_folder_list):
  12. for p in excluded_folder_list:
  13. var_pattern.sub(process_var_sub, p)
  14. for i in range(len(excluded_folder_list)):
  15. excluded_folder_list[i] = excluded_folder_list[i] + "\\"
  16. excluded_folder_list = {
  17. 'name': policy_name + " "+section+" Exclusions",
  18. 'description': "",
  19. 'items': excluded_folder_list
  20. }
  21. payload = json.dumps(excluded_folder_list, indent=4)
  22. print(payload)
  23. url = baseurl + "directorylists"
  24. response = requests.request("POST", url, headers=headers, data=payload)
  25. print(response.text)
  26. del response
  27. del url
  28. del excluded_folder_list
  29. del payload
  30. else:
  31. return

EDIT 2:

Ok, it's a hack job, I know, but I got it to work. Any suggestions on cleaning it up?

  1. def write_folder_exception_list(excluded_folder_list, policy_name, section):
  2. if len(excluded_folder_list):
  3. for i in range(len(excluded_folder_list)):
  4. excluded_folder_list_cleaned = [
  5. var_pattern.sub(process_var_sub, p)
  6. for p in excluded_folder_list
  7. ]
  8. excluded_folder_list = excluded_folder_list_cleaned
  9. excluded_folder_list[i] = excluded_folder_list[i] + "\\"
  10. excluded_folder_list = {
  11. 'name': policy_name + " "+section+" Exclusions",
  12. 'description': "",
  13. 'items': excluded_folder_list_cleaned
  14. }
  15. payload = json.dumps(excluded_folder_list, indent=4)
  16. print(payload)

EDIT 3:

I was able to get it working (and made a few more optimizations to my code) thanks to shadowtalkers input. I'm sure it can be cleaned up and optimized more, but here are the snippets of the relative code if someone else has to deal with this in the future.

  1. # Pattern to recognize when performing the Folder Exceptions
  2. var_pattern = re.compile(r"%([^%]+)%")
  3. # Function to swap out the '%' symbols in environment variables from Apex One
  4. def process_var_sub(match):
  5. var_name = match.group(1)
  6. return "${" + var_name.lower() + "}"
  7. # Populate elements from the JSON File
  8. def populate_elements(policy_filename):
  9. with open(policy_filename) as jsonFile: # Open the file as a JSON file
  10. data = json.load(jsonFile) # Read the file
  11. policyname = (data['policy'][0]['policyName']) # Get the name of the policy as seen in Apex One
  12. dictionary = (data['policy'][0]['managedSettings']) # Read the managedSettings section (which holds the users custom data)
  13. settings = json.loads(dictionary) # Read the settings as it's own JSON string
  14. return policyname, [settings]
  15. # Function to write Folder Exceptions using the API
  16. def write_folder_exception_list(excluded_folder_list, policy_name, section):
  17. if len(excluded_folder_list):
  18. for i in range(len(excluded_folder_list)):
  19. excluded_folder_list_cleaned = [
  20. var_pattern.sub(process_var_sub, p)
  21. for p in excluded_folder_list
  22. ]
  23. excluded_folder_list = excluded_folder_list_cleaned
  24. excluded_folder_list[i] = excluded_folder_list[i] + "\\"
  25. excluded_folder_list = {
  26. 'name': policy_name + " "+section+" Exclusions",
  27. 'description': "",
  28. 'items': excluded_folder_list_cleaned
  29. }
  30. payload = json.dumps(excluded_folder_list, indent=4)
  31. url = baseurl + "directorylists"
  32. response = requests.request("POST", url, headers=headers, data=payload)
  33. print(response.text)
  34. del response
  35. del url
  36. del excluded_folder_list
  37. del payload
  38. else:
  39. return
  40. # Open JSON policy file(s) within the current working directory the script is run in
  41. for file in os.listdir(): # Get a list of files in the directory
  42. policy_filename = os.fsdecode(file) # Pull the file name
  43. if policy_filename.endswith(".policy"): # Make sure we're only working with the .policy files
  44. policyName, settings = populate_elements(policy_filename) # Call the function to populate the managed_settings information
  45. for settings in settings: # Iterate the settings to populate fields
  46. # RTS Exclusions
  47. RTSExcludedFolders = (settings["managed_settings"][0]["settings"][1]["value"]['ExcludedFolder'])
  48. RTSExcludedFiles = (settings["managed_settings"][0]["settings"][3]["value"]['ExcludedFile'])
  49. RTSExcludedExtensions = (settings["managed_settings"][0]["settings"][5]["value"]['ExcludedExt'])
  50. write_folder_exception_list(RTSExcludedFolders, policyName, "RTS Scan")
  51. write_extensions_exception_list(RTSExcludedExtensions, policyName, "RTS Scan")
  52. write_filename_exception_list(RTSExcludedFiles, policyName, "RTS Scan")

答案1

得分: 1

一般来说,你想替换任何形式为%...%的_pattern_,这对于正则表达式来说是一项很棒的工作。

首先,你需要匹配所需的_pattern_,并捕获其中的文本。使用正则表达式%([^%]+)%就足够了:

  1. % 字面量"%"
  2. ( 开始捕获组
  3. [^%] 任何字符,除了"%"
  4. + 重复前一个字符1次或更多次
  5. ) 结束捕获组
  6. % 字面量"%"

在这里进一步探索这个正则表达式:


现在我们可以使用Python的一个不错的特性,即使用一个_function_在捕获的结果上执行正则替换:

  1. import re
  2. var_pattern = re.compile(r"%([^%]+)%")
  3. def process_var_sub(match):
  4. var_name = match.group(1)
  5. return "${" + var_name.lower() + "}"
  6. paths_in = [
  7. r"C:\Temp\Folder1",
  8. r"C:\Temp\Folder2",
  9. r"C:\Temp\Folder3",
  10. r"C:\Temp\Folder4",
  11. r"%ALLUSERSPROFILE%\Temp",
  12. r"%WINDIR%\Temp",
  13. ]
  14. paths_out = [
  15. var_pattern.sub(process_var_sub, p)
  16. for p in paths_in
  17. ]
  18. assert paths_out == [
  19. r"C:\Temp\Folder1",
  20. r"C:\Temp\Folder2",
  21. r"C:\Temp\Folder3",
  22. r"C:\Temp\Folder4",
  23. r"${allusersprofile}\Temp",
  24. r"${windir}\Temp",
  25. ]

这个特性在https://docs.python.org/3/library/re.html#re.sub中有文档:

> 如果 repl 是一个函数,它将在每次非重叠出现 pattern 时调用。

最后,注意使用 r"" 防止Python在引号内解释 \ 为特殊字符。

英文:

In general, you are looking to replace any pattern of the form %...%, which seems like a great job for regular expressions.

First, you need to match the desired pattern, and capture the text within. This is easy enough with the regex %([^%]+)%:

  1. % literal "%"
  2. ( start a capture group
  3. [^%] any character other than "%"
  4. + repeat the previous character 1 or more times
  5. ) end the capture group
  6. % literal "%"

See here to explore this regex further:


Now we can use a nice Python feature and use a function to perform regex substitution on the captured result:

  1. import re
  2. var_pattern = re.compile(r"%([^%]+)%")
  3. def process_var_sub(match):
  4. var_name = match.group(1)
  5. return "${" + var_name.lower() + "}"
  6. paths_in = [
  7. r"C:\Temp\Folder1",
  8. r"C:\Temp\Folder2",
  9. r"C:\Temp\Folder3",
  10. r"C:\Temp\Folder4",
  11. r"%ALLUSERSPROFILE%\Temp",
  12. r"%WINDIR%\Temp",
  13. ]
  14. paths_out = [
  15. var_pattern.sub(process_var_sub, p)
  16. for p in paths_in
  17. ]
  18. assert paths_out == [
  19. r"C:\Temp\Folder1",
  20. r"C:\Temp\Folder2",
  21. r"C:\Temp\Folder3",
  22. r"C:\Temp\Folder4",
  23. r"${allusersprofile}\Temp",
  24. r"${windir}\Temp",
  25. ]

This feature is documented in https://docs.python.org/3/library/re.html#re.sub:

> If repl is a function, it is called for every non-overlapping occurrence of pattern.

Finally, note the use of r"" to prevent Python from interpreting \ as a special character inside the quotes.

huangapple
  • 本文由 发表于 2023年3月15日 21:10:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75745195.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定