os.Getenv()的反向函数或库

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

Reverse function or library for os.Getenv()

问题

我有一个 REG_EXPAND_SZ 类型的十六进制字符串列表。

示例:
reg,[HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node], "Pathethic"=hex(2):43,00,3a,00,5c,00,57,00,49,00,4e,00,44,00,4f,00,57,00,53,00,\00,00
//忽略解析和格式化部分。

我需要将其转换为原始字符串。

期望输出:
%systemroot%

实际输出:
C:\Windows

问题在于当用户最初运行命令终端时,它会展开它:reg add HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node /v Pathetic /t REG_EXPAND_SZ /d "%systemroot%". 稍后使用实际展开的字符串。例如:初始 %systemroot% = 实际 C:\Windows。当我将十六进制字符串转换为常规字符串时,我得到了 C:\Windows。

这就是为什么我想知道是否有任何库或工具可以通过提供值来获取键,即反向。C:\Window :=os.Getenv(???)。

我尝试手动完成,但展开的字符串比我预期的要多。因此,我的程序受到限制。请为此问题提供任何解决方案。

func reverseEnvVar(value string) string {
    // 使用 os.ExpandEnv() 来展开输入字符串中的环境变量
    expanded := os.ExpandEnv(value)

    // 检查展开后的字符串是否与已知的环境变量值匹配
    switch expanded {
    case os.Getenv("SystemRoot"):
        return "%systemroot%"
    case os.Getenv("ProgramFiles"):
        return "%programfiles%"
    case os.Getenv("ProgramFiles(x86)"):
        return "%programfiles(x86)%"
    case os.Getenv("AppData"):
        return "%appdata%"
    case os.Getenv("LocalAppData"):
        return "%localappdata%"
    case os.Getenv("UserProfile"):
        return "%userprofile%"
    case os.Getenv("TEMP"):
        return "%temp%"
    case os.Getenv("TMP"):
        return "%tmp%"
    default:
        // 如果展开后的字符串与已知的环境变量值不匹配,
        // 返回原始输入值
        return value
    }
}

这是一个用于反向获取环境变量的函数。它使用 os.ExpandEnv() 来展开输入字符串中的环境变量,并检查展开后的字符串是否与已知的环境变量值匹配。如果匹配,则返回相应的环境变量名,否则返回原始输入值。你可以将这个函数用于你的程序中,以便将展开后的字符串转换回原始字符串。

英文:

I have a list of hexadecimal strings of REG_EXPAND_SZ type.
Sample:
reg,[HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node], "Pathethic"=hex(2):43,00,3a,00,5c,00,57,00,49,00,4e,00,44,00,4f,00,57,00,53,00,\00,00
//Ignore the parsing and formatting part.

I need to convert it to the original string.

Expected output:
%systemroot%

Actual output:
C:\Windows

The problem is that when user initially run the command terminal expands it: reg add HKEY_LOCAL_MACHINE\SOFTWAR\WOW6432Node /v Pathetic /t REG_EXPAND_SZ /d "%systemroot%". Later the actual expanded string is used. For example: initial %systemroot% = actual C:\Windows. When I convert hex string to the regular one I get C:\Windows.

That is why I wonder if there any library or tool to get the key by providing value, meaning reverse. C:\Window :=os.Getenv(???).

package main

import (
	"encoding/hex"
	"fmt"
	"log"
	"os"
)

func CToGoString(b []byte) string {
	var buf []byte
	for _, c := range b {
		if c != 0 {
			buf = append(buf, c)
		}
	}
	return string(buf)
}

func main() {

	str := "43003a005c00570049004e0044004f00570053000000" //%systemroot%
	bs, err := hex.DecodeString(str)
	if err != nil {
		panic(err)
	}
	//s := CToGoString(bs)
	result := CToGoString(bs)
	fmt.Println(result)

	f, err := os.OpenFile("rollback.bat", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		log.Fatal(err)
	}

	f.WriteString(result + "\n")

}

I have tried doing it manually but there are more expanded strings than I expected. Therefore, my program is limited. Please advise any solutions for this problem.
`

func reverseEnvVar(value string) string {
    // Use os.ExpandEnv() to expand environment variables in the input string
    expanded := os.ExpandEnv(value)

    // Check if the expanded string matches a known environment variable value
    switch expanded {
    case os.Getenv("SystemRoot"):
        return "%systemroot%"
    case os.Getenv("ProgramFiles"):
        return "%programfiles%"
    case os.Getenv("ProgramFiles(x86)"):
        return "%programfiles(x86)%"
    case os.Getenv("AppData"):
        return "%appdata%"
    case os.Getenv("LocalAppData"):
        return "%localappdata%"
    case os.Getenv("UserProfile"):
        return "%userprofile%"
    case os.Getenv("TEMP"):
        return "%temp%"
    case os.Getenv("TMP"):
        return "%tmp%"
    default:
        // If the expanded string doesn't match a known environment variable value,
        // return the original input value
        return value
    }
}

答案1

得分: 0

我没有找到一个可以将C:\WINDOWS转换为%systemroot%的库,但可以使用os.Environ()来实现。

导入:

import (
	"errors"
	"fmt"
	"os"
	"strings"
)

值 -> 键数组的哈希映射:

func createEnvHashMap() map[string][]string {
    envMap := make(map[string][]string)

    for _, env := range os.Environ() {
        pair := strings.SplitN(env, "=", 2)
        if len(pair) == 2 {
            key := fmt.Sprintf("%%%s%%", strings.ToLower(pair[0]))
            value := pair[1]
            envMap[value] = append(envMap[value], key)
        }
    }

    return envMap
}

根据返回列表的函数:

func getEnvKeysByValue(envMap map[string][]string, value string) ([]string, error) {
    keys, found := envMap[value]
    if !found {
        return nil, errors.New("未找到该值的环境变量键")
    }
    return keys, nil
}

现在你可以在主函数中使用**getEnvKeysByValue()**函数:

func main() {

    // 创建环境变量及其键的映射
	envMap := createEnvHashMap()

	// 这个值可以用你的main()函数中的结果变量替换
	value := "C:\\WINDOWS"

	// 根据值获取环境变量键
	keys, err := getEnvKeysByValue(envMap, value)
	if err != nil {
		fmt.Println("错误:", err)
		return
	}

	fmt.Println("环境变量键:")
	for _, key := range keys {
		fmt.Println(key)
	}
}

输出:

环境变量键:
%systemroot%
%windir%

这样就不需要手动编写switch case语句了。
确保只调用一次createEnvHashMap(),然后可以多次调用getEnvKeysByValue(envMap, value)以在O(1)时间内获取键列表。

英文:

I didn't find a library that takes C:\WINDOWS and gives %systemroot% but it can easily be implemented using os.Environ().

Imports:

import (
	"errors"
	"fmt"
	"os"
	"strings"
)

<br>

Hashmap for value -> array of keys:

func createEnvHashMap() map[string][]string {
    envMap := make(map[string][]string)

    for _, env := range os.Environ() {
        pair := strings.SplitN(env, &quot;=&quot;, 2)
        if len(pair) == 2 {
            key := fmt.Sprintf(&quot;%%%s%%&quot;, strings.ToLower(pair[0]))
            value := pair[1]
            envMap[value] = append(envMap[value], key)
        }
    }

    return envMap
}

<br>

Function to return the list of keys given the value:

func getEnvKeysByValue(envMap map[string][]string, value string) ([]string, error) {
    keys, found := envMap[value]
    if !found {
        return nil, errors.New(&quot;no environment variable keys found for the value&quot;)
    }
    return keys, nil
}

<br>

Now you can use the getEnvKeysByValue() function in you main function:

func main() {

    // Create a map of environment variables and their keys
	envMap := createEnvHashMap()

	// This value can be replaced with the result variable in your main() function
	value := &quot;C:\\WINDOWS&quot;

	// Get environment variable keys by value
	keys, err := getEnvKeysByValue(envMap, value)
	if err != nil {
		fmt.Println(&quot;Error:&quot;, err)
		return
	}

	fmt.Println(&quot;Environment variable keys:&quot;)
	for _, key := range keys {
		fmt.Println(key)
	}
}

<br>

Output:

Environment variable keys:
%systemroot%
%windir%

This way there won't be a need to write switch case statements manually.
<br>
Make sure to call createEnvHashMap() only once and then call getEnvKeysByValue(envMap, value) as many times to get list of keys in O(1) time.

huangapple
  • 本文由 发表于 2023年7月6日 15:26:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76626428.html
匿名

发表评论

匿名网友

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

确定