The issue where command substitution strips all trailing newlines comes up
regularly (eg. on this list [1] and stackoverflow [2]).  This behavior is
historical and mandated by POSIX, and ensures that doing something like:

    now=$(date)
    echo "$now"

or:

    now=$(date)
    cat <<<$now

is equivalent to just running date (since it would be very surprising if it
wasn't).  But, because $() strips (potentially) many trailing newlines, whereas
echo or <<< add back only one newline, this breaks down when commands might
output 0 or 2+ trailing newlines.

There are at least 3 common workarounds:

    foo=$(some_command ... ; rc=$? ; echo . ; exit $rc)
    rc=$?
    foo=${foo%.}

    orig_REPLY=$(declare -p REPLY)
    read -rd '' < <(some_command ...) || [[ $REPLY ]]
    foo=$REPLY
    eval $orig_REPLY
    unset -v orig_REPLY

    mapfile < <(some_command ...)
    printf -v foo %s "${MAPFILE[@]}"

In the past I have used these workarounds when necessary, however, IMHO they
are all ugly, non-idiomatic, require relatively deep understanding of nuanced
shell behavior, and are difficult to get exactly right, eg. the first needs
hoop-jumping to retain $?, the second requires hoop-jumping to avoid clobbering
$REPLY (and doing:

    read -rd '' foo < <(some_command ...) || [[ $foo ]]

doesn't work as might be expected, I think because read with no names is a
special case), and the third would require similar to avoid clobbering
$MAPFILE.  The ugliness can sometimes be hidden, eg. by encapsulating them into
a function such as:

    function grab_output {
        if [ "$1" != output ]; then
            declare -n output="$1"
        fi
        shift
        output=$(eval "${@-cat}" ; rc=$? ; echo . ; exit $rc)
        local rc=$?
        output=${output%.}
        return $rc
    }

but this still results in non-idiomatic code, because now you have to write:

    grab_output foo some_command ...

or with shopt -s lastpipe:

    some_command ... | grab_output foo

when what you actually mean (idiomatically) is:

    foo=$(some_command ...)

I now have a use case which involves various combinations of command pipelines,
with output sometimes stored in shell variables for inspection, before being
finally output or fed into later pipelines.  Bash is well suited for this, but
in my use case:

1. The text input/output protocol between the various programs is line
oriented, and sensitive to trailing newline stripping (ie. they should be
preserved).  (Briefly, each line is an independent input containing zero or
more space-separated words, and an empty line with no words still means
something specific and must be processed as usual.  I can go into more detail
if required.)

2. It's important that authors of these pipelines shouldn't need to be bash
experts, and should be able to just use "normal" idiomatic bash code (ie. I
don't want to have a library of helpers like grab_output, and have to tell
authors that they have to remember to always use grab_output instead of doing
foo=$(bar), etc etc).

All of this means that what I really want is to tell bash not to strip trailing
newlines from command substitution, and correspondingly to not add a trailing
newline to here strings.  (Here documents, being line-oriented with a
line-based terminator, are unaffected, since their structure in the bash script
is such that it always makes sense to add a trailing newline.)

Attached is a patch which does this.  The actual code changes are very simple -
it adds two shopts (cmdsubst_trailing_nls which defaults to off, and
herestr_trailing_nl which defaults to on), and two if statements which guard
the code that strips/adds the trailing newlines.  (The subst.c change looks
worse because of the increased indentation, but diff -b shows that it's just
wrapping the newline stripping code inside the newly added if statement.)  I
also added test suite coverage and documentation updates.

Is this something that could be considered for adding to bash?

I expect the maintenance burden from these changes would be low, but the main
potential issues are (1) the choice of using shopts to modify behavior (vs
alternative syntax ala [3]; each of these approaches has pros and cons), and
(2) what the shopts ought to be named (for which I have no strong preference).

As an illustrative example, without this change my scripts look like:

    shopt -s lastpipe

    some | complex | pipeline | grab_output my_result
    while :; do
        if is_any_good "$my_result"; then
            break
        else
            echo -n "$my_result" | some | further | processing |
grab_output my_result
        fi
    done
    echo -n "$my_result" | final_processing

whereas with the change, I think they are much more idiomatic, and basically
identical to what I would write if trailing newlines were irrelevant (which is
exactly what I'm aiming for):

    shopt -s cmdsubst_trailing_nls
    shopt -u herestr_trailing_nl

    my_result=$(some | complex | pipeline)
    while :; do
        if is_any_good "$my_result"; then
            break
        else
            my_result=$(some <<<$my_result | further | processing)
        fi
    done
    final_processing <<<$my_result

Thanks,

Kev

[1] https://lists.gnu.org/archive/html/bug-bash/2007-05/msg00041.html
    https://lists.gnu.org/archive/html/bug-bash/2010-07/msg00090.html
    https://lists.gnu.org/archive/html/bug-bash/2017-06/msg00058.html
    https://lists.gnu.org/archive/html/bug-bash/2021-01/msg00259.html
[2] https://unix.stackexchange.com/a/383411
    https://unix.stackexchange.com/a/606739
[3] https://lists.gnu.org/archive/html/bug-bash/2021-01/msg00269.html
diff --git a/builtins/shopt.def b/builtins/shopt.def
index cf6f6be..18811aa 100644
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -96,6 +96,8 @@ extern int varassign_redir_autoclose;
 extern int singlequote_translations;
 extern int patsub_replacement;
 extern int bash_source_fullpath;
+extern int cmdsubst_trailing_nls;
+extern int herestr_trailing_nl;
 
 #if defined (EXTENDED_GLOB)
 extern int extended_glob;
@@ -194,6 +196,7 @@ static struct {
 #if defined (HISTORY)
   { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
 #endif
+  { "cmdsubst_trailing_nls", &cmdsubst_trailing_nls, (shopt_set_func_t *)NULL },
   { "compat31", &shopt_compat31, set_compatibility_level },
   { "compat32", &shopt_compat32, set_compatibility_level },
   { "compat40", &shopt_compat40, set_compatibility_level },
@@ -224,6 +227,7 @@ static struct {
   { "globskipdots", &glob_always_skip_dot_and_dotdot, (shopt_set_func_t *)NULL },
   { "globstar", &glob_star, (shopt_set_func_t *)NULL },
   { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
+  { "herestr_trailing_nl", &herestr_trailing_nl, (shopt_set_func_t *)NULL },
 #if defined (HISTORY)
   { "histappend", &force_append_history, (shopt_set_func_t *)NULL },
 #endif
@@ -378,6 +382,8 @@ reset_shopt_options (void)
   singlequote_translations = 0;
   patsub_replacement = PATSUB_REPLACE_DEFAULT;
   bash_source_fullpath = BASH_SOURCE_FULLPATH_DEFAULT;
+  cmdsubst_trailing_nls = 0;
+  herestr_trailing_nl = 1;
 
 #if defined (JOB_CONTROL)
   check_jobs_at_exit = 0;
diff --git a/doc/bash.1 b/doc/bash.1
index 5af3492..0596c71 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -4119,7 +4119,11 @@ or (deprecated)
 .B Bash
 performs the expansion by executing \fIcommand\fP in a subshell environment
 and replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
+command, with any trailing newlines deleted (unless
+.B cmdsubst_trailing_nls
+is set using the
+.BR shopt (1)
+builtin).
 Embedded newlines are not deleted, but they may be removed during
 word splitting.
 The command substitution \fB$(cat \fIfile\fP)\fR can be replaced by
@@ -4143,7 +4147,10 @@ There is an alternate form of command substitution:
 .RE
 .PP
 which executes \fIcommand\fP in the current execution environment
-and captures its output, again with trailing newlines removed.
+and captures its output, again with trailing newlines removed (unless
+.B cmdsubst_trailing_nls
+is set using
+.BR shopt (1)).
 .PP
 The character \fIc\fP following the open brace must be a space, tab,
 newline, or \fB|\fP, and the close brace must be in a position
@@ -4168,7 +4175,9 @@ including the positional parameters, is shared with the caller.
 If the first character following the open brace
 is a \fB|\fP, the construct expands to the
 value of the \fBREPLY\fP shell variable after \fIcommand\fP executes,
-without removing any trailing newlines,
+without removing any trailing newlines (this behavior is not affected by the
+.B cmdsubst_trailing_nls
+shopt option),
 and the standard output of \fIcommand\fP remains the same as in the
 calling shell.
 \fBBash\fP creates \fBREPLY\fP as an initially-unset local variable when
@@ -4957,7 +4966,12 @@ The \fIword\fP undergoes
 tilde expansion, parameter and variable expansion,
 command substitution, arithmetic expansion, and quote removal.
 Pathname expansion and word splitting are not performed.
-The result is supplied as a single string, with a newline appended,
+The result is supplied as a single string, with a newline appended
+(unless the
+.B herestr_trailing_nl
+shell option is unset using the
+.BR shopt (1)
+builtin),
 to the command on its
 standard input (or file descriptor \fIn\fP if \fIn\fP is specified).
 .SS "Duplicating File Descriptors"
@@ -11921,6 +11935,14 @@ under
 .BR HISTORY .
 .PD 0
 .TP 8
+.B cmdsubst_trailing_nls
+If set, command substitution preserves trailing newlines from the command's
+output before substitution occurs. If unset (the default), trailing newlines
+are removed for the standard \fB$(\fP\fIcommand\fP\fB)\fP and legacy
+\fB`\fP\fIcommand\fP\fB`\fP forms, as well as the alternate \fB${\fP
+\fIcommand\fP\fB;}\fP form. The \fB${|\fP\fIcommand\fP\fB;}\fP form always
+preserves trailing newlines in \fBREPLY\fP and is not affected by this option.
+.TP 8
 .B compat31
 .TP 8
 .B compat32
@@ -12121,6 +12143,11 @@ subdirectories match.
 If set, shell error messages are written in the standard GNU error
 message format.
 .TP 8
+.B herestr_trailing_nl
+If set (the default), here strings (of the form \fB<<<\fP\fIword\fP)
+have a trailing newline appended to \fIword\fP before being passed to
+the command. If unset, the string is passed without modification.
+.TP 8
 .B histappend
 If set, the history list is appended to the file named by the value
 of the
diff --git a/doc/bashref.texi b/doc/bashref.texi
index 138a0f9..c687a01 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -2835,7 +2835,8 @@ or (deprecated)
 @noindent
 Bash performs command substitution by executing @var{command} in a subshell
 environment and replacing the command substitution with the standard
-output of the command, with any trailing newlines deleted.
+output of the command, with any trailing newlines deleted (unless the
+@code{cmdsubst_trailing_nls} @code{shopt} option is set).
 Embedded newlines are not deleted, but they may be removed during
 word splitting.
 The command substitution @code{$(cat @var{file})} can be
@@ -2857,7 +2858,8 @@ $@{@var{c} @var{command}; @}
 
 @noindent
 which executes @var{command} in the current execution environment
-and captures its output, again with trailing newlines removed.
+and captures its output, again with trailing newlines removed (unless
+the @code{cmdsubst_trailing_nls} @code{shopt} option is set).
 
 The character @var{c} following the open brace must be a space, tab,
 newline, or @samp{|}, and the close brace must be in a position
@@ -2882,7 +2884,8 @@ including the positional parameters, is shared with the caller.
 If the first character following the open brace
 is a @samp{|}, the construct expands to the
 value of the @code{REPLY} shell variable after @var{command} executes,
-without removing any trailing newlines,
+without removing any trailing newlines (this behavior is not affected by
+the @code{cmdsubst_trailing_nls} @code{shopt} option),
 and the standard output of @var{command} remains the same as in the
 calling shell.
 Bash creates @code{REPLY} as an initially-unset local variable when
@@ -3542,7 +3545,8 @@ The @var{word} undergoes
 tilde expansion, parameter and variable expansion,
 command substitution, arithmetic expansion, and quote removal.
 Filename expansion and word splitting are not performed.
-The result is supplied as a single string, with a newline appended,
+The result is supplied as a single string, with a newline appended
+(unless the @code{herestr_trailing_nl} shell option is unset),
 to the command on its
 standard input (or file descriptor @var{n} if @var{n} is specified).
 
@@ -6326,6 +6330,15 @@ This allows easy re-editing of multi-line commands.
 This option is enabled by default, but only has an effect if command
 history is enabled (@pxref{Bash History Facilities}).
 
+@item cmdsubst_trailing_nls
+If set, command substitution preserves trailing newlines from the
+command's output before substitution occurs. If unset (the default),
+trailing newlines are removed for the standard @code{$(@var{command})}
+and legacy @code{`@var{command}`} forms, as well as the alternate
+@code{$@{ @var{command}; @}} form. The @code{$@{| @var{command}; @}}
+form always preserves trailing newlines in @code{REPLY} and is not
+affected by this option.
+
 @item compat31
 @itemx compat32
 @itemx compat40
@@ -6465,6 +6478,11 @@ subdirectories match.
 If set, shell error messages are written in the standard @sc{gnu} error
 message format.
 
+@item herestr_trailing_nl
+If set (the default), here strings (of the form @code{<<< @var{word}})
+have a trailing newline appended to @var{word} before being passed to
+the command. If unset, the string is passed without modification.
+
 @item histappend
 If set, the history list is appended to the file named by the value
 of the @env{HISTFILE}
diff --git a/redir.c b/redir.c
index 343536b..0973c84 100644
--- a/redir.c
+++ b/redir.c
@@ -88,6 +88,9 @@ extern int errno;
 int expanding_redir;
 int varassign_redir_autoclose = 0;
 
+/* If non-zero, here-strings append a trailing newline. */
+int herestr_trailing_nl = 1;
+
 extern REDIRECT *redirection_undo_list;
 extern REDIRECT *exec_redirection_undo_list;
 
@@ -383,8 +386,8 @@ heredoc_expand (WORD_DESC *redirectee, enum r_instruction ri, size_t *lenp)
   executing_builtin = old;
 
   dlen = STRLEN (document);
-  /* XXX - Add trailing newline to here-string */
-  if (ri == r_reading_string)
+  /* Add trailing newline to here-string unless disabled by shopt */
+  if (ri == r_reading_string && herestr_trailing_nl)
     {
       document = xrealloc (document, dlen + 2);
       document[dlen++] = '\n';
diff --git a/subst.c b/subst.c
index e9d3e75..f1126e6 100644
--- a/subst.c
+++ b/subst.c
@@ -197,6 +197,9 @@ int fail_glob_expansion;
    pattern substitution word expansion. */
 int patsub_replacement = PATSUB_REPLACE_DEFAULT;
 
+/* If non-zero, command substitution preserves trailing newlines. */
+int cmdsubst_trailing_nls = 0;
+
 /* Are we executing a ${ command; } nofork comsub? */
 int executing_funsub = 0;
 
@@ -6770,37 +6773,41 @@ read_comsub (int fd, int quoted, int flags, int *rflag)
       return (char *)NULL;
     }
 
-  /* Strip trailing newlines from the output of the command. */
-  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+  /* Strip trailing newlines from the output of the command unless
+     preservation is enabled via shopt cmdsubst_trailing_nls. */
+  if (cmdsubst_trailing_nls == 0)
     {
-      while (istring_index > 0)
+      if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
 	{
-	  if (istring[istring_index - 1] == '\n')
+	  while (istring_index > 0)
 	    {
-	      --istring_index;
-
-	      /* If the newline was quoted, remove the quoting char. */
-	      if (istring[istring_index - 1] == CTLESC)
-		--istring_index;
-
-#ifdef __MSYS__
-	      if (istring_index > 0 && istring[istring_index - 1] == '\r')
+	      if (istring[istring_index - 1] == '\n')
 		{
 		  --istring_index;
 
-		  /* If the carriage return was quoted, remove the quoting char. */
+		  /* If the newline was quoted, remove the quoting char. */
 		  if (istring[istring_index - 1] == CTLESC)
 		    --istring_index;
-		}
+
+#ifdef __MSYS__
+		  if (istring_index > 0 && istring[istring_index - 1] == '\r')
+		    {
+		      --istring_index;
+
+		      /* If the carriage return was quoted, remove the quoting char. */
+		      if (istring[istring_index - 1] == CTLESC)
+			--istring_index;
+		    }
 #endif
+		}
+	      else
+		break;
 	    }
-	  else
-	    break;
+	  istring[istring_index] = '\0';
 	}
-      istring[istring_index] = '\0';
+      else
+	strip_trailing (istring, istring_index - 1, 1);
     }
-  else
-    strip_trailing (istring, istring_index - 1, 1);
 
   if (rflag)
     *rflag = tflag;
diff --git a/tests/complete.right b/tests/complete.right
index 1b7893b..a70e2e9 100644
--- a/tests/complete.right
+++ b/tests/complete.right
@@ -182,6 +182,7 @@ checkhash
 checkjobs
 checkwinsize
 cmdhist
+cmdsubst_trailing_nls
 compat31
 compat32
 compat40
@@ -204,6 +205,7 @@ globasciiranges
 globskipdots
 globstar
 gnu_errfmt
+herestr_trailing_nl
 histappend
 histreedit
 histverify
diff --git a/tests/comsub-newlines.right b/tests/comsub-newlines.right
new file mode 100644
index 0000000..60e5910
--- /dev/null
+++ b/tests/comsub-newlines.right
@@ -0,0 +1,9 @@
+[A
+
+]
+[B
+
+]
+[C
+
+]
diff --git a/tests/comsub-newlines.tests b/tests/comsub-newlines.tests
new file mode 100644
index 0000000..485f79e
--- /dev/null
+++ b/tests/comsub-newlines.tests
@@ -0,0 +1,22 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Verify that enabling cmdsubst_trailing_nls preserves trailing newlines
+# in command substitutions for legacy backticks, $(), and ${ cmd; } forms.
+
+shopt -s cmdsubst_trailing_nls
+
+echo "[`printf 'A\n\n'`]"
+echo "[$(printf 'B\n\n')]"
+echo "[${ printf 'C\n\n'; }]"
+
diff --git a/tests/herestr-trailing.right b/tests/herestr-trailing.right
new file mode 100644
index 0000000..9e86d31
--- /dev/null
+++ b/tests/herestr-trailing.right
@@ -0,0 +1,21 @@
+Testing herestr_trailing_nl behavior
+Default behavior:
+declare -a MAPFILE=([0]=$'test\n')
+Disabled behavior:
+declare -a MAPFILE=([0]="test")
+Empty string default:
+declare -a MAPFILE=([0]=$'\n')
+Empty string disabled:
+declare -a MAPFILE=()
+Multiple words default:
+declare -a MAPFILE=([0]=$'hello world\n')
+Multiple words disabled:
+declare -a MAPFILE=([0]="hello world")
+Multiline default:
+declare -a MAPFILE=([0]=$'foo\n' [1]=$'bar\n')
+Multiline disabled:
+declare -a MAPFILE=([0]=$'foo\n' [1]="bar")
+Multiline with trailing newline default:
+declare -a MAPFILE=([0]=$'foo\n' [1]=$'bar\n' [2]=$'\n')
+Multiline with trailing newline disabled:
+declare -a MAPFILE=([0]=$'foo\n' [1]=$'bar\n')
diff --git a/tests/herestr-trailing.tests b/tests/herestr-trailing.tests
new file mode 100644
index 0000000..dbcaee0
--- /dev/null
+++ b/tests/herestr-trailing.tests
@@ -0,0 +1,75 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Test herestr_trailing_nl shopt option behavior
+
+echo "Testing herestr_trailing_nl behavior"
+
+# Test 1: Default behavior (should add trailing newline)
+echo "Default behavior:"
+mapfile <<<"test"
+declare -p MAPFILE
+
+# Test 2: Disabled behavior (should not add trailing newline)
+echo "Disabled behavior:"
+shopt -u herestr_trailing_nl
+mapfile <<<"test"
+declare -p MAPFILE
+shopt -s herestr_trailing_nl
+
+# Test 3: Empty string - default
+echo "Empty string default:"
+mapfile <<<""
+declare -p MAPFILE
+
+# Test 4: Empty string - disabled
+echo "Empty string disabled:"
+shopt -u herestr_trailing_nl
+mapfile <<<""
+declare -p MAPFILE
+shopt -s herestr_trailing_nl
+
+# Test 5: Multiple words - default
+echo "Multiple words default:"
+mapfile <<<"hello world"
+declare -p MAPFILE
+
+# Test 6: Multiple words - disabled
+echo "Multiple words disabled:"
+shopt -u herestr_trailing_nl
+mapfile <<<"hello world"
+declare -p MAPFILE
+
+# Test 7: Multiline string - default
+echo "Multiline default:"
+shopt -s herestr_trailing_nl
+mapfile <<<$'foo\nbar'
+declare -p MAPFILE
+
+# Test 8: Multiline string - disabled
+echo "Multiline disabled:"
+shopt -u herestr_trailing_nl
+mapfile <<<$'foo\nbar'
+declare -p MAPFILE
+
+# Test 9: Multiline with trailing newline - default
+echo "Multiline with trailing newline default:"
+shopt -s herestr_trailing_nl
+mapfile <<<$'foo\nbar\n'
+declare -p MAPFILE
+
+# Test 10: Multiline with trailing newline - disabled
+echo "Multiline with trailing newline disabled:"
+shopt -u herestr_trailing_nl
+mapfile <<<$'foo\nbar\n'
+declare -p MAPFILE
diff --git a/tests/invocation.right b/tests/invocation.right
index 304fc91..aa85f22 100644
--- a/tests/invocation.right
+++ b/tests/invocation.right
@@ -72,9 +72,9 @@ Shell options:
 this-bash this-bash
 $- for -c includes c
 bash: line 0: badopt: invalid shell option name
-checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
-checkhash:checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
-cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:herestr_trailing_nl:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+checkhash:checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:herestr_trailing_nl:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:herestr_trailing_nl:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
 ./invocation1.sub: line 40: BASHOPTS: readonly variable
 braceexpand:hashall:interactive-comments
 braceexpand:hashall:interactive-comments
diff --git a/tests/run-comsub-newlines b/tests/run-comsub-newlines
new file mode 100644
index 0000000..17a07b0
--- /dev/null
+++ b/tests/run-comsub-newlines
@@ -0,0 +1,2 @@
+${THIS_SH} ./comsub-newlines.tests > ${BASH_TSTOUT} 2>&1
+diff ${BASH_TSTOUT} comsub-newlines.right && rm -f ${BASH_TSTOUT}
diff --git a/tests/run-herestr-trailing b/tests/run-herestr-trailing
new file mode 100755
index 0000000..996989f
--- /dev/null
+++ b/tests/run-herestr-trailing
@@ -0,0 +1,2 @@
+${THIS_SH} ./herestr-trailing.tests > ${BASH_TSTOUT} 2>&1
+diff ${BASH_TSTOUT} herestr-trailing.right && rm -f ${BASH_TSTOUT}
diff --git a/tests/shopt.right b/tests/shopt.right
index 2d47b57..d70b195 100644
--- a/tests/shopt.right
+++ b/tests/shopt.right
@@ -11,6 +11,7 @@ shopt -u checkhash
 shopt -u checkjobs
 shopt -u checkwinsize
 shopt -s cmdhist
+shopt -u cmdsubst_trailing_nls
 shopt -u compat31
 shopt -u compat32
 shopt -u compat40
@@ -33,6 +34,7 @@ shopt -s globasciiranges
 shopt -s globskipdots
 shopt -u globstar
 shopt -u gnu_errfmt
+shopt -s herestr_trailing_nl
 shopt -u histappend
 shopt -u histreedit
 shopt -u histverify
@@ -73,6 +75,7 @@ shopt -s extquote
 shopt -s force_fignore
 shopt -s globasciiranges
 shopt -s globskipdots
+shopt -s herestr_trailing_nl
 shopt -s hostcomplete
 shopt -s interactive_comments
 shopt -s patsub_replacement
@@ -88,6 +91,7 @@ shopt -u cdable_vars
 shopt -u checkhash
 shopt -u checkjobs
 shopt -u checkwinsize
+shopt -u cmdsubst_trailing_nls
 shopt -u compat31
 shopt -u compat32
 shopt -u compat40
@@ -134,6 +138,7 @@ cdable_vars         	off
 checkhash           	off
 checkjobs           	off
 checkwinsize        	off
+cmdsubst_trailing_nls	off
 compat31            	off
 compat32            	off
 compat40            	off

Reply via email to