Strange behavior of argv when passing string containing “!!!!”

爷,独闯天下 提交于 2019-11-29 11:16:19

问题


I have written a small program that takes some input parameters from *argv[] and prints them. In almost all use cases my code works perfectly fine. A problem only arises when I use more than one exclamation mark at the end of the string I want to pass as an argument ...

This works:

./program -m "Hello, world!"

This does NOT work:

./program -m "Hello, world!!!!"

^^ If I do this, the program output is either twice that string, or the command I entered previous to ./program.

However, what I absolutely don't understand: The following, oddly enough, DOES work:

./program -m 'Hello, world!!!!'

^^ The output is exactly ...

Hello, world!!!!

... just as desired.

So, my questions are:

  • Why does this strange behavior occur when using multiple exclamation marks in a string?
  • As far as I know, in C you use "" for strings and '' for single chars. So why do I get the desired result when using '', but not when using "" as I should (in my understanding)?
  • Is there a mistake in my code or what do I need to change to be able to enter any string (no matter if, what, and how many punctuation marks are used) and get exactly that string printed?

The relevant parts of my code:

// this is a simplified example that, in essence, does the same 
// as my (significantly longer) code
int main(int argc, char* argv[]) {
    char *msg = (char *)calloc(1024, sizeof(char));

    printf("%s", strcat(msg, argv[2])); // argv[1] is "-m"

    free(msg);
}

I already tried copying the content of argv[2] into a char* buffer first and appending a '\0' to it, which didn't change anything.


回答1:


This is not related to your code but to the shell that starts it.

In most shells, !! is shorthand for the last command that was run. When you use double quotes, the shell allows for history expansion (along with variable substitution, etc.) within the string, so when you put !! inside of a double-quoted string it substitutes the last command run.

What this means for your program is that all this happens before your program is executed, so there's not much the program can do except check if the string that is passed in is valid.

In contrast, when you use single quotes the shell does not do any substitutions and the string is passed to the program unmodified.

So you need to use single quotes to pass this string. Your users would need to know this if they don't want any substitution to happen. The alternative is to create a wrapper shell script that prompts the user for the string to pass in, then the script would subsequently call your program with the proper arguments.




回答2:


The shell does expansion in double-quoted strings. And if you read the Bash manual page (assuming you use Bash, which is the default on most Linux distributions) then if you look at the History Expansion section you will see that !! means

Refer to the previous command.

So !!!! in your double-quoted string will expand to the previous command, twice.

Such expansion is not made for single-quoted strings.

So the problem is not within your program, it's due to the environment (the shell) calling your program.




回答3:


In addition to the supplied answers, you should remember that echo is your shell friend. If you prefix your command with "echo ", you will see what shell is actually sending to your script.

echo ./program -m "Hello, world!!!!"

This would have showed you some strangeness and might have helped steer you in the right direction.



来源:https://stackoverflow.com/questions/48687023/strange-behavior-of-argv-when-passing-string-containing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!