Bash脚本提取含嵌入换行的变量值失败,如何修复?
问题描述
我有一个内容如下的文件input.txt:
export k="v"
其中v可能包含\n(嵌入换行符)这类字符。目标是将不带双引号的v存储到与变量同名的文件中(如示例中的k文件)。
例如,若输入为:
export a_a="foooo barrrrr"
应将以下内容存储到名为a_a的文件中:
foooo barrrrr
注意:内容可能是多行的,且无法过多控制输入格式。
我尝试用以下代码实现:
key=$(cat "$filename" | cut -d '=' -f 1 | cut -d ' ' -f 2) key_size= echo $key | wc -c echo key_size trim_size=$(( $key_size + 9 )) value=$(cat "$filename" | cut -c $trim_size- | rev | cut -c 2- | rev) echo -n "$value"> $key
期望得到:
foooo barrrrr
但实际只得到:
foooo
问题出在value=$(cat "$filename" | cut -c $trim_size- | rev | cut -c 2- | rev)这一行,希望该行将嵌入换行符\n视为数据的一部分,请问该如何修复?
解决方案
问题根源
- 变量赋值错误:
key_size= echo $key | wc -c没有用$()捕获命令输出,导致key_size为空值,后续trim_size计算完全错误。 cut工具的局限性:cut -c是逐行处理文本的,当内容包含换行时,只有第一行有export key="的前缀,后续行没有该前缀,按固定字符数截取会直接截断或丢失后续行内容。- 边界识别失效:原逻辑无法正确识别多行内容的结尾双引号,导致截断部分内容。
修复方案
推荐使用awk或sed这类支持多行处理的工具,以下是两种可行的实现:
方案1:使用awk(简洁高效)
filename="input.txt" # 提取变量名key key=$(awk -F'=' '/^export / {sub(/^export /,""); print $1}' "$filename") # 提取双引号内的多行内容并写入对应文件 awk -v key="$key" -v RS='"' 'NR==2 {print > key}' "$filename"
逻辑说明:
- 将记录分隔符
RS设为双引号",文本会被分割为三个部分:export key=、目标内容v、结尾换行。 NR==2对应双引号包裹的内容部分,直接将其写入名为key的文件。
方案2:使用sed(适配复杂格式)
filename="input.txt" # 提取变量名key key=$(sed -n 's/^export \([^=]*\)=".*/\1/p' "$filename") # 提取并处理多行内容 sed -n ' s/^export '"$key"'="//; # 去掉开头的export key=" :a; # 定义循环标签 N; # 读取下一行到当前缓冲区 /"$/!ba; # 如果缓冲区末尾不是",回到标签a继续读取 s/"$//; # 去掉结尾的" p # 输出处理后的内容 ' "$filename" > "$key"
逻辑说明:
- 先替换第一行的前缀,通过循环读取所有行直到找到结尾的双引号,最后去掉结尾的引号并输出到目标文件。
验证效果
用示例输入测试上述脚本,会在当前目录生成a_a文件,内容为:
foooo barrrrr
内容的提问来源于stack exchange,提问作者Amin Ba
相关产品推荐
相关产品推荐

