In a shell script...
How do I capture stdin to a variable without stripping any trailing newlines?
Right now I have tried:
var=`cat`
var=`tee`
var=$(tee)
In all cases $var
will not have the trailing newline of the input stream. Thanks.
ALSO: If there is no trailing newline in the input, then the solution must not add one.
UPDATE IN LIGHT OF THE ACCEPTED ANSWER:
The final solution that I used in my code is as follows:
function filter() {
#do lots of sed operations
#see https://github.com/gistya/expandr for full code
}
GIT_INPUT=`cat; echo x`
FILTERED_OUTPUT=$(printf '%s' "$GIT_INPUT" | filter)
FILTERED_OUTPUT=${FILTERED_OUTPUT%x}
printf '%s' "$FILTERED_OUTPUT"
If you would like to see the full code, please see the github page for expandr, a little open-source git keyword-expansion filter shell script that I developed for information security purposes. According to rules set up in .gitattributes files (which can be branch-specific) and git config, git pipes each file through the expandr.sh shell script whenever checking it in or out of the repository. (That is why it was critical to preserve any trailing newlines, or lack thereof.) This lets you cleanse sensitive information, and swap in different sets of environment-specific values for test, staging, and live branches.
filter
takesstdin
- it runssed
. You catchstdin
in$GIT_INPUT
then print that back tostdout
over a pipe tofilter
and catch itsstdout
in$FILTERED_OUTPUT
and then print it back tostdout
. All 4 lines at the bottom of your example above could be replaced with just this:filter
. No offense meant here, it's just... you're working too hard. You don't need the shell variables most of the time - just direct the input to the right place and pass it on.filter
, then it will add newline characters to the ends of any input streams that did not end in newlines initially. In fact I originally did just dofilter
but ran into that problem which led me to this solution because neither "always add newlines" nor "always strip newlines" are acceptable solutions.sed
probably will do the extra newline - but you should handle that infilter
not with all the rest. And all of those functions that you have basically do the same thing - ased s///
. You're using the shell to pipe data it has saved in its memory tosed
so thatsed
might replace that data with other data that the shell has stored in its memory sosed
can pipe it back to the shell. Why not just[ "$var" = "$condition" ] && var=new_value
? I also don't get the arrays - are you storing the array name in[0]
then usingsed
to replace that with the value in[1]
? Maybe chat?filter
? It works perfectly as-is. Regarding how the code at my link works and why I set it up the way that I did, yeah, lets talk about it in a chat room.