1

I'm searching for a possibility to send via pipe several multiline strings to a bash script and grab each of them within this script. Finally, I want to store each multiline string into its own variable.

printf "$some_multiline_string" "$another_multiline_string" | some_script.sh some_params

Inside of bash:

#!/bin/bash
file1=$(</dev/stdin)
file2=$(</dev/stdin)
...

How to split stdin into multiple multiline variables?

  • 1
    How would you know when file1's input was done? – Jeff Schaller Nov 24 '16 at 12:49
  • Why don't you use the multiline strings as parameters, and keep them with ${@} to get the number of parameters, and then run with a simple loop and assign them to var? – Chen A. Nov 24 '16 at 12:58
  • I tried to pass them as parameteres. and it worked, but seems there is a limit, which I'm easily reaching with large files. – playmobox Nov 24 '16 at 13:00
  • If you have very long streams, then use files. Keep them into single file where each line describes a string, then make the script to run on it. Or you can make each string a file, and run over a list of files. – Chen A. Nov 24 '16 at 13:02
  • So i should put each multiline string into it's own (temporary) file and read their content from within the bash script? if yes, i hope this intermediate will not take too much time else....? Had the hope there is a more easy but still super fast way to pass huge data (from php) to a shell script? – playmobox Nov 24 '16 at 13:11
3

Why not use the environment?

export some_multiline_string another_multiline_string

And then you can access those variables from within the script.

If they may be very large and exceed the maximum size of an argument/envvar or if combined they exceed the maximum size of the arg+env list, then you could pass them with pipes:

myscript 3< <(printf %s "$some_multiline_string") \
         4< <(printf %s "$another_multiline_string") args

And within myscript:

IFS= read -rd '' -u3 var1
IFS= read -rd '' -u4 var2
exec 3<&- 4<&-

Or you could pass them from within a single stream for instance on the script's stdin but delimited with NUL (which in bash can't occur in a variable):

printf '%s\0' "$some_multiline_string" "$another_multiline_string" |
  myscript args

And within myscript:

IFS= read -rd '' var1 && IFS= read -rd '' var2
2

I'm not entirely sure I understand your question, but I think what you are looking for is:

script.sh "$some_multiline_string" "$another_multiline_string" param1 param2

Then, inside the script, you would have:

file1="$1"
file2="$2"
param1="$3"
param2="$4"

If you really need to pipe it, you could do something like this:

printf '%s\0%s' "$str1" "$str2" | script.sh param1 param2

And, in the script:

#!/bin/bash
param1="$1"
param2="$2"

strings=()
while IFS= read -d '' str; do
    strings+=("$str")
done
printf 'String 1: %s\n\nString 2: %s\n' "${strings[0]}" "${strings[1]}"

For example:

$ str1="this is
a multiline
string"

$ str2="this is
another multiline
string"

$ printf '%s\0%s\0' "$str1" "$str2" | foo.sh
String 1: this is
a multiline
string

String 2: this is
another multiline
string

In bash versions 4.4+, you can do:

#!/bin/bash
param1="$1"
param2="$2"

strings=()
readarray -t -d '' strings

printf 'String 1: %s\n\nString 2: %s\n' "${strings[0]}" "${strings[1]}"
  • Thank you all, this and the top one solution helped me a lot. – playmobox Nov 26 '16 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.