从C ++中的argv正确处理字符串中的转义序列

时间:2016-07-05 17:59:30

标签: c++ escaping special-characters

我正在编写一个更大的程序,它在可执行文件后从命令行获取参数。一些参数预计将在选项的等号后传递。例如,默认情况下,日志的输出是逗号分隔的向量,但如果用户想要将分隔符更改为句点或其他内容而不是逗号,则可以将参数指定为:

./main --separator="."

这样可以正常工作,但是如果用户希望分隔符是特殊字符(例如:tab),则他们可能希望以下列方式之一传递转义序列:

./main --separator="\t"
./main --separator='\t'
./main --separator=\t

它的行为方式与我想要的方式不同(将\ t解释为标签)而是将字符串打印出来(没有引号,没有引号只是打印't')。我尝试过使用双斜线,但我想我可能只是接近这个错误而且我不确定如何正确地问这个问题(我试过搜索)。

我在这里以虚拟示例重新创建了这个问题:

#include <string>
#include <iostream>
#include <cstdio>

// Pull the string value after the equals sign
std::string get_option( std::string input );
// Verify that the input is a valid option
bool is_valid_option( std::string input );

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

    if ( argc != 2 )
    {
        std::cerr << "Takes exactly two arguments.  You gave " << argc << "." << std::endl;

        exit( -1 );
    }

    // Convert from char* to string

    std::string arg ( argv[1] );

    if ( !is_valid_option( arg ) )
    {
        std::cerr << "Argument " << arg << " is not a valid option of the form --<argument>=<option>." << std::endl;

        exit( -2 );
    }

    std::cout << "You entered: " << arg << std::endl;
    std::cout << "The option you wanted to use is: " << get_option( arg ) << "."  << std::endl;

    return 0;
}

std::string get_option( std::string input )
{
    int index = input.find( '=' );
    std::string opt = input.substr( index + 1 ); // We want everything after the '='
    return opt;
}

bool is_valid_option( std::string input )
{
    int equals_index = input.find('=');

    return ( equals_index != std::string::npos && equals_index < input.length() - 1 );
}

我这样编译:

g++ -std=c++11 dummy.cpp -o dummy

使用以下命令,它会产生以下输出。

双引号:

/dummy --option="\t"
You entered: --option=\t
The option you wanted to use is: \t.

单引号:

./dummy --option='\t'
You entered: --option=\t
The option you wanted to use is: \t.

没有引号:

./dummy --option=\t
You entered: --option=t
The option you wanted to use is: t.

我的问题是:有没有办法指定它应该将子字符串\ t解释为制表符(或其他转义序列)而不是字符串文字“\ t”?我可以手动解析它,但我正试图避免重新发明轮子,因为我可能只是遗漏了一些小东西。

非常感谢你的时间和答案。这是非常简单的事情,它让我疯狂,我不知道如何快速简单地修复它。

1 个答案:

答案 0 :(得分:3)

转义序列已经从您使用的shell中解析,并相应地传递给命令行参数数组2016-07-05 20:11:28,335 http-bio-8080-exec-2917 anonymous 1211x943864x1 - 10.000.000.113,10.000.105.000 /rest/api/2/search HttpSession created [10n1nec] 2016-07-05 20:11:28,381 http-bio-8080-exec-2917 AABBCC 1211x943864x1 - 10.000.000.000,10.000.105.000 /rest/api/2/search The user 'AABBCC' has PASSED authentication.

正如您所注意到的,只有引用的版本才能让您检测到argv字符串已被解析并传递给您的"\\t"
由于大多数shell可能只是跳过真正的TAB字符作为空格,所以你永远不会在命令行参数中看到它。

但是如上所述,它主要是shell如何解释命令行的问题,以及如何使用c ++或c来处理程序调用参数。

  

我的问题是:有没有办法指定它应该将子字符串\ t解释为制表符(或其他转义序列)而不是字符串文字“\ t”?我可以手动解析它,但我正试图避免重新发明轮子,因为我可能只是遗漏了一些小东西。

您实际上需要扫描字符串文字

main()

在c ++代码中。