0

I'm trying to:

  1. Accept input in bash and store it verbatim to a file
  2. cat the contents of the file.

Any special characters should also be written verbatim to the file.

Sample Input

./verbatim.sh -a smb 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]''

Expected output

Inner single quotes should remain enter image description here

-a smb 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]''

Actual output

Inner quotes are stripped

-a smb 'ngrep -i -d $INTERFACE s.?a.?m.?b.?a.*[[:digit:]]'

Code

#!/bin/bash
#
# Script Name: verbatim.sh
chars='[ !"#$&()*,;<>?\^`{|}]'
for arg
do
    if [[ $arg == *\'* ]]
    then
        arg=\""$arg"\"
    elif [[ $arg == *$chars* ]]
    then
        arg="'$arg'"
    fi
    allargs+=("$arg")    # ${allargs[@]} is to be used only for printing
done
printf '%s\n' "${allargs[*]}" > /tmp/pse.tmp

cat /tmp/pse.tmp

I'm not sure if bash can accomplish what I am asking or not?

Would this be better to accept using read or IFS? The goal of my script is to append the user's input to a file that will be used as a "quick reference" for a particular service.

brakertech
  • 1,395
  • You don't have any "inner single quotes": https://unix.stackexchange.com/questions/187651/how-to-echo-single-quote-when-using-single-quote-to-wrap-special-characters-in Also: use printf %q or "${var@Q}" instead of rolling your own quoting – muru May 28 '20 at 02:40
  • I've highlighted the inner single quotes in a picture that i just attached to the question. – brakertech May 28 '20 at 03:01
  • Did you read the linked post? You don't have any "inner single quotes". In 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]'', you have one single-quoted string 'ngrep -i -d $INTERFACE ' followed by unquoted s.?a.?m.?b.?a.*[[:digit:]], followed by the single-quoted empty string ''. – muru May 28 '20 at 03:32
  • No wonder this doesn't work, thanks @muru – brakertech May 28 '20 at 03:39
  • This question is not about accepting input and storing it verbatim. It's about giving input verbatim to a script on the command line. At least that is the issue. – Kusalananda May 28 '20 at 06:53

2 Answers2

1

The question on the title

Once a variable contains an specific string, it wont be expanded a second time (if quoted).

So, for the example case you presented (convert all ' to '\''):

var='-a smb '\''ngrep -i -d $INTERFACE '\''s.?a.?m.?b.?a.*[[:digit:]]'\'''\'''

Or, reduced a little (not actually needed, but nicer to remove consecutive ''):

var='-a smb '\''ngrep -i -d $INTERFACE '\''s.?a.?m.?b.?a.*[[:digit:]]'\'\'

Will print this (the string you want):

$ echo "$var"
-a smb 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]''

And will give an script that same string:

$ ./verbatim.sh "$var"

If the (verbatim.sh) script is:

#!/bin/bash
printf '<%s>' "$@"; echo

It will print:

$ ./verbatim.sh "$var"
<-a smb 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]''>

a verbatim string of what you wrote.

Write to file:

If you want to write that input to a file, you can extend the verbatim.sh script to:

#!/bin/bash

printf '<%s>' "$@"; echo
printf '%s\n' "$var" > /tmp/pse.tmp

And then:

$ cat /tmp/pse.tmp
-a smb 'ngrep -i -d $INTERFACE 's.?a.?m.?b.?a.*[[:digit:]]''

Will give you the output you are asking for.

Problems

The above works because I have been careful to process the string inside "$var" as a single string, not arguments.

  • The first thing your script do is to ask for a list of arguments in:

    for arg do .......
    

    There is one single argument: an string. If you need a list of arguments the process must be entirely different.

  • Then you try to quote each separate argument with double or single quotes. No, that won't work either.

  • And,reading the contents of the string you provide, you seem to be trying to build a command and execute it. That is even worse. You must read I'm trying to put a command in a variable, but the complex cases always fail!

Then, maybe, edit this question to use arrays for arguments.

0

It is not possible.

If you run the following

     myprog a
     myprog \a
     myprog "a"
     myprog 'a'

then in all 4 cases the value that myprog will get for the first argument will be a pointer to the string "a", and you can't tell which you were given. Therefore you can't write out what you were given verbatim This is because the arguments are processed before myprog is even invoked.

icarus
  • 17,920