Linux Bash变量无法保留换行符的问题排查与解决
问题
我在Debian Stable Linux系统中工作,想要修改apt search zypper的输出格式,把每组非空的两行合并成一行。
原命令输出:
$ apt search zypper Sorting... Done Full Text Search... Done libzypp-bin/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (library tools) libzypp-common/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (common files) libzypp-config/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (configuration) libzypp-dev/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (development files) libzypp-doc/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (documentation) libzypp1722/stable 17.25.7-1 amd64 openSUSE/SLES package management system (library) zypper/stable 1.14.42-1 amd64 command line software manager using libzypp zypper-common/stable,stable 1.14.42-1 all command line software manager using libzypp (common files) zypper-doc/stable,stable 1.14.42-1 all command line software manager using libzypp (documentation)
我用了以下sed命令处理,直接运行时输出符合预期:
$ apt search zypper | sed ':a;N;s/\n\(\.\)/ \1/;ta' WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Sorting... Full Text Search... libzypp-bin/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (library tools) libzypp-common/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (common files) libzypp-config/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (configuration) libzypp-dev/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (development files) libzypp-doc/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (documentation) libzypp1722/stable 17.25.7-1 amd64 openSUSE/SLES package management system (library) zypper/stable 1.14.42-1 amd64 command line software manager using libzypp zypper-common/stable,stable 1.14.42-1 all command line software manager using libzypp (common files) zypper-doc/stable,stable 1.14.42-1 all command line software manager using libzypp (documentation)
但把输出存入变量再用echo $var输出时,所有行被合并成一长行:
var=`apt search zypper | sed ':a;N;s/\n\(\.\)/ \1/;ta'` echo $var
输出结果:
Sorting... Full Text Search... libzypp-bin/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (library tools) libzypp-common/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (common files) libzypp-config/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (configuration) libzypp-dev/stable 17.25.7-1 amd64 openSUSE/SLES package management system library (development files) libzypp-doc/stable,stable 17.25.7-1 all openSUSE/SLES package management system library (documentation) libzypp1722/stable 17.25.7-1 amd64 openSUSE/SLES package management system (library) zypper/stable 1.14.42-1 amd64 command line software manager using libzypp zypper-common/stable,stable 1.14.42-1 all command line software manager using libzypp (common files) zypper-doc/stable,stable 1.14.42-1 all command line software manager using libzypp (documentation)
需要保留换行符维持各行独立,请问问题出在哪?怎么解决?
原因与解决方法
问题原因
Bash中,当你执行echo $var时,未加引号的变量展开会触发分词操作:变量内的所有空白字符(包括换行、空格、制表符)都会被替换成单个空格,同时还会处理通配符匹配,这就是换行消失的原因。
解决办法
1. 用双引号包裹变量输出
给变量加上双引号,Bash会保留变量内的换行符和原始空格结构:
var=$(apt search zypper | sed ':a;N;s/\n\(\.\)/ \1/;ta') echo "$var"
注:推荐用$(...)替代反引号`...`,前者可读性更强,支持嵌套使用。
2. 直接输出,跳过变量存储
如果不需要后续复用处理后的内容,直接执行管道命令即可,避免变量展开带来的问题:
apt search zypper | sed ':a;N;s/\n\(\.\)/ \1/;ta'
额外优化:改进sed命令
原sed命令会把Sorting... Done和Full Text Search... Done合并成一行,如果你想保留这两行的独立换行,可以调整sed逻辑,只合并以空格开头的包描述行:
apt search zypper | sed '/^[[:space:]]/{N;s/\n[[:space:]]+/ /;}'
这个命令会匹配以空白字符开头的行,将其与上一行合并,替换换行和开头的空格为单个空格,结果更贴合原始输出的结构。
内容的提问来源于stack exchange,提问作者rnso
相关产品推荐
相关产品推荐

