0

I have a script that runs another script for each line in a file.

When I echo each $line I can see the full contents of the line as expected.

Yet inside connect.sh only $1 is set as user\ name.

When I try using "$line", $1 in connect.sh ends up being user\ name user\ password.

How can I setup the program flow so that reboot.sh passes each line of /tmp/history to connect.sh as 2 parameters.

With the end result that $1 is user\ name and $2 is user\ password?

reboot.sh:

if [ -e "/tmp/history" ]; then
  while read -r line; do
    echo $line
    connect.sh $line \
      && break
  done </tmp/history
fi

connect.sh:

echo $1
echo $2

/tmp/history:

user\ name user\ password

2 Answers2

2

I assume the backslashes are there to escape the two spaces so that they don't separate the values.

With read -r line you get the whole line in the variable line, so that line contains user\ name user\ password, with the backspaces. It's not easy to split that without tricks with eval. An unquoted $line will get split on whitespace, backslashes or not. Quoted, it expands into one word, as you saw.

Luckily, read can handle backslashes and split its input into two (or more) variables. This would have the variables contain user name and user password (with the backslashes removed):

while read user pass ; do 
    echo "user: $user"
    echo "pass: $pass"
    ./connect.sh "$user" "$pass"
done < file

However, if you want to allow whitespace in the username and the password, it might be better to use some other delimiter than space. A colon is common, so you'd have an input like this:

user name:user pass word

And then read it with

while IFS=: read -r user pass ; do 
    echo "user: $user"
    echo "pass: $pass"
done < file          

(That should work as long as the password doesn't end with a colon)

ilkkachu
  • 138,973
0

If you have an argument with spaces in it, you'll need to make sure you double quote the string to prevent connect.sh from interpreting it as multiple arguments. You may want to split the string into multiple arguments. I'm not sure what the format of the line is, but you may be able to do something like this:

line="user name user password"
# Split the line into space-separated tokens and store 1 and 2
UNAME=$(echo "$line" | cut -d ' ' -f 1,2)
# Split the line into space-separated tokens and store 3 and 4
UPASSWD=$(echo "$line" | cut -d ' ' -f 3,4)
echo "$UNAME"
echo "$UPASSWD"

This should print:

user name
user password

You'll likely need to make some adjustments based on the actual format of the input line. For example, if your $line has the user name and user password separated by a comma, you could run:

line="user name,user password"
# Split the line into comma-separated tokens and store 1
UNAME=$(echo "$line" | cut -d ',' -f 1)
# Split the line into comma-separated tokens and store 2
UPASSWD=$(echo "$line" | cut -d ',' -f 2)
echo "$UNAME"
echo "$UPASSWD"

Just remember that if you're passing an argument to a program and that argument has spaces, you'll need to use double quotes to make the program see it as one argument.

John Moon
  • 1,013