如何使用sscanf解析C中的环境变量

问题描述 投票:-2回答:2

我一直在这里寻找每一个sscanf帖子,但找不到适合我问题的确切解决方案。我正在实现自己的Shell,其特点之一是,如果我发现美元符号$,则必须用环境变量替换它后面的数字:

[cd $HOME实际上应该在我执行cd之前就由cd /home/user代替。

我的问题是,使用sscanf取出美元符号并简单地在同一字符串上获得HOME的代码是什么?我一直在尝试使用一些null指针进行尝试:

char * change;
if (strcmp(argv[1][0],'$')==0){

   change = malloc(strlen(argv[y]));
   sscanf(argv2[y]+1,"%[_a-zA-Z0-9]",change);
   argv2[y]=getenv(change);

但是这似乎失败了,我有一个分段错误核心。 (如果需要,我可以放更多的代码,我的问题专门针对sscanf)。快速说明argv是指向输入和解析的行的指针的数组,因此实际上是argv[0] = "cd"argv[1]="$HOME"的内容。我也知道$之后要接收的变量具有以下格式:%[_a-zA-Z0-9]

编辑:请忽略非失败处理。

c scanf
2个回答
1
投票

您在代码中询问“是否需要malloc()”,答案为“否”,可以使用一个简单的数组。实际上,如果您只是在同一个作用域中使用getenv()的返回值而不进行修改,而没有对getenv()的任何其他调用,那么您所需要的只是一个指针。 getenv()将返回一个指向程序环境中value对的name=value部分的指针。但是,该指针可能是指向静态分配的数组的指针,因此在使用该指针之前,对getenv()的任何其他调用都可能导致文本更改。另外,请勿修改getenv()返回的字符串,否则您将修改进程的环境。

也就是说,对于您的简单案例,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXC 1024   /* if you need a constant, #define one (or more) */

int main (int argc, char **argv) {

    char *envp = NULL,      /* pointer for return of getenv() */
        buf[MAXC];          /* buffer to parse argv[2] w/sscanf */

    if (argc < 3) { /* validate at least 2 program arguments given */
        printf ("usage: %s cmd path\n", strrchr (argv[0], '/') + 1);
        return 1;
    }

    if (*argv[2] == '$')    /* chest 1st char of argv[2] == '$' */
        if (sscanf (argv[2] + 1, "%1023[_a-zA-Z0-9]", buf) != 1) {
            fputs ("error: invalid format following '$'.\n", stderr);
            return 1;
        }

    if (!(envp = getenv (buf))) {   /* get environment var from name in buf */
        fprintf (stderr, "'%s' not found in environment.\n", buf);
        return 1;
    }

    printf ("%s %s\n", argv[1], envp);  /* output resulting command line */
}

现在,程序在检索环境变量后仅输出结果命令行。您可以根据需要调整和构建execv的指针数组。

示例使用/输出

$ ./bin/getenvhome "cd" '$HOME'
cd /home/david

仔细检查,如果还有其他问题,请通知我。


1
投票

这里不需要sscanf,只需滑动指针即可。

如果argv[1]指向字符串"$HOME",则argv[1] + 1指向"HOME",因此您的示例代码将变成:]]

char * change;
if (argv[y][0] == '$')
{
    change = argv[y] + 1;
}

((但在这种情况下,您的变量不应命名为change。将变量称为它们代表什么

,例如在本例中为variable_name,因为它包含将要扩展的shell变量的名称。 -请记住您的代码用于与他人交流您的意图和有关该代码的其他有用信息。)

为清楚起见,无论您是执行sscanf还是该技巧,您仍然必须进行错误检查以确保变量名实际上是正确的字符。

[请记住,sscanf不会告诉您是否有错误的字符,它只会停止-如果用户编写了一个像$FO)O这样的变量(因为他们在尝试键入$FOO时输入了错字)[C0 ]只会扫描出第一个有效字符,而忽略无效字符,然后返回sscanf

在这种情况下,最后忽略不正确的数据将很糟糕,因为用户界面(包括外壳)应该最大程度地减少用户错误地无意间执行意外错误的可能性。

© www.soinside.com 2019 - 2024. All rights reserved.