Call function in bash script with arguments from file with spaces

I want to execute a command with arguments read from a file. This works fine until 1 of the arguments has a space.

I tried grouping words with quotes and backslashes, but none of them worked.

The functionality that I am is exactly what xargs does, except that I need to call the function, not the command, because it relies on other variables set elsewhere in the script

script:

 do_echo() { echo '$1:' $1 echo '$2:' $2 } line=`cat input.txt` #cat used for simplicity, can have more than 1 line do_echo $line 

input.txt:

 "hello world" "hello back" 

Expected Result:

 $1: hello world $2: hello back 

Observed result:

 $1: "hello $2: world" 

EDIT:

I use this to execute the same command several times with different inputs. There are up to 15 parameters in a line and can be higher than 50 lines.

A tabular format would be ideal, although the current response to entering each parameter in a row would work.

+4
source share
2 answers

Unaccounted variables (as in do_echo $line ) are strictly divided into any character that is in the IFS variable (by default, this value is set to tab, space, new line). Strictly means that it is really strict, there is no way to quote or avoid splitting.

The main workaround is to define an otherwise unnecessary character (for example, a colon : as a separator character.

eg

 $ cat input.txt hello world:hello back $ line=$(head -n 1 input.txt) $ OLDIFS=$IFS IFS=: $ do_echo $line $1: hello world $2: hello back $ IFS=$OLDIFS 

Another workaround is using eval , but eval is dangerous. You absolutely must trust the input!

 $ cat input.txt "hello world" "hello back" $ line=$(head -n 1 input.txt) $ eval do_echo "$line" $1: hello world $2: hello back 
+4
source

Instead of using quotation marks, separate each argument with a character that is guaranteed not to appear in a separate argument. For example, using a semicolon:

 hello world;hello back argument 1;argument 2 

You can then read the set of arguments, one batch at a time, using read :

 while IFS=';' read -a arguments; do do_echo "${arguments[@]}" done < input.txt 

An obscure ASCII control character, such as the unit delimiter (ASCII 0x1f), will be less likely to appear in the argument if you can enter them in your file.

+3
source

All Articles