7

Is there any way to read raw text from stdin before it is expanded or before the shell does anything to it? Say I wanted to run a script where a user enters a string which is then printed out, how can I get the following behavior:

$ sh test.sh
Please enter a string:
***<><><||&&*&$PATH

You entered:
***<><><||&&*&$PATH

Is there any way to implicitly surround the text with '' or escape all meta characters even if the user does not?

gambol
  • 73

2 Answers2

8

Try doing this :

$ read -r -p 'Please enter a string >>> ' var
$ printf '%q\n' "$var"
\*\*\*\<\>\<\>\<\|\|\&\&\*\&\$PATH
0

The expansion, if any, is happening when you print, not when you read. (as Giles said, the magic is in the %q. But even echo "$var" is not expanded). Read gets all the literal characters into the variable, except backslash. Echo of the bare variable is expanded. Echo of the variable in a "quote" string is not expanded:

xxmetac.sh:

#!/bin/bash
read str
echo you entered:
echo $str
echo "$str"

test:

$ ls
file1 file2 file3

$ xxmetac.sh
*
you entered:
file1 file2 file3
*

Also most shell metacharacters are not special even when echoed. Probably only the file-globbing ones:

*?[-]{,}

Not special:

!#@$^%()|<>

$ xxmetac.sh
>
you entered:
>
>

$ xxmetac.sh
|
you entered:
|
|

$ xxmetac.sh
@$^%()|<>
you entered:
@$^%()|<>
@$^%()|<>

They are special on the command line

$ !#@$^%()|<>
@$^%()|<>
bash: syntax error near unexpected token `|'