Sed处理多行文件内容变量时报错,求解决方案
I see the issue here—when your variable $a contains newlines, embedding it directly into the sed substitution command breaks things. Sed parses commands line-by-line, so the newlines in $a split the s command into incomplete chunks, hence the "unterminated `s' command" error.
Let’s break down practical solutions to fix this, depending on whether you want to flatten the multi-line content into a single line or preserve its original line breaks:
Solution 1: Flatten Multi-Line Content Into a Single Line
If you want to merge all lines from the file into one continuous string (matching your expected output format), first strip newlines and escape characters that would break sed’s substitution logic:
# Read file, remove newlines, and escape sed special characters (&, \, /) a=$(tr -d '\n' < file | sed -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\&/g') # Use | as the sed delimiter to avoid conflicts with / in content sed "/^[[:blank:]]*\"data_$2\": \[$/,/^[[:blank:]]*],*$/ {s|^[[:blank:]]*}$|&$a|}" "$1"
Why this works:
tr -d '\n'removes all newlines from the file content, ensuring$ais a single line.- The
sedescape steps handle characters with special meaning in substitutions (backslashes, slashes, and ampersands) to prevent unexpected behavior. - Using
|instead of/as the substitution delimiter avoids conflicts if your file content contains slashes.
Solution 2: Preserve Original Line Breaks
If you want to keep the file’s line breaks (even if it makes the JSON technically invalid), escape newlines as \n so sed interprets them correctly:
# Read entire file into one line, escape special chars, replace newlines with \n a=$(sed -e ':a' -e 'N' -e '$!ba' -e 's/\\/\\\\/g' -e 's/\//\\\//g' -e 's/&/\\&/g' -e 's/\n/\\n/g' file) sed "/^[[:blank:]]*\"data_$2\": \[$/,/^[[:blank:]]*],*$/ {s|^[[:blank:]]*}$|&$a|}" "$1"
How this works:
:a;N;$!bais a sed trick to read the entire file into a single buffer (instead of processing line-by-line).- We escape special characters first, then replace each newline with
\n—sed will render this as a literal newline in the output.
Solution 3: Avoid Variables Entirely (Simplest Approach)
Skip storing the file content in a variable altogether, and have sed directly read the file at the target position using the r command:
sed "/^[[:blank:]]*\"data_$2\": \[$/,/^[[:blank:]]*],*$/ { /^[[:blank:]]*}$/ { # Append file content right after the closing } s/^[[:blank:]]*}$/&/ r file } }" "$1"
Note:
This inserts the file content on a new line after the }. If you need it on the same line as the }, stick with Solutions 1 or 2.
Testing With Your Example
For a file with content:
yeah is test my script
Solution 1 will produce exactly your expected output:
{ "mytable_test": [ { "test1": "abc", "test2": "def", "test2": "ghi" }yeah is test my script ], "mytable": [ "test1", "test2", "test3" ] }
内容的提问来源于stack exchange,提问作者Mathie

