How to interpret special characters in command lin

2019-03-03 16:39发布

问题:

First problem:

Suppose we write a simple program which takes in command line arguments and prints to a file. If the user enters

writetofile Hello!0\n w%orl\t!@#y

bash replies with

!0: event not found.

Without the user knowing things like using quotes ('') or escape characters ('\'), how do I handle this stuff instead of bash understanding it as a command?

Second problem:

Once I get these arguments, how do I interpret them as special characters and not sequences of characters. (ie. \t is tab, not '\''t')

That is, how do make sure that the program writes this to the file:

Hello!0
 w%orl    !@#y

and not

Hello!0\n w%orl\t!@#y

回答1:

Regarding the second problem: as @Jims said, you could use printf(1) to print the string. Good idea, but be aware that that would work only because the escapes you (appear to) want to recognise, like \t and \n, are the same as the ones that printf recognises.

These escapes are common, but there's nothing fundamental about them, so the general answer to your question – and the answer if you want to recognise an escape that printf doesn't – is for your program to interpret them. The C-like code to do that would be something like:

char *arg = "foo\\tbar\\n"; /* the doubled backslashes are to make this valid C */
int arglen = strlen(arg);
for (i=0; i<arglen; i++) {
    if (arg[i] == '\\') { // we've spotted an escape
        // interpret a backslash escape
        i++; // we should check for EOS here...
        switch (arg[i]) {
          case 'n': putchar('\n'); break;
          case 't': putchar('\t'); break;
          // etc
         }
     } else {
         // ordinary character: just output it
         putchar(arg[i]);
     }
 }

(insert error handling and good style, to taste).



回答2:

You can't get bash to stop parsing a command line as a command line. In your particular case, set +H would disable history expansion, thus allowing !0 as a literal, but a command would still fail if you included (parenthesis), $variables, #comments, ampersand & and a dozen other elements of shell syntax.

Note that this only applies to the parsing stage of the shell, not for any data that is passed literally into execve or similar.

Either make the user quote the data ('single quotes' will take care of everything except other single quotes), or make your program read the data itself so that the interaction goes

$ writetofile
Please enter your gibberish and press enter: Hello!0\n w%orl\t!@#y
Thank you for your eloquent contribution.
$


回答3:

First problem: Use single quotes. ie: writetofile 'Hello!0\n w%orl\t!@#y'

Second problem: Use printf.