多行变量删除换行符 - 鱼

use*_*492 2 shell fish

当我将任何多行文本设置为fish中的变量时,它会删除新行字符并用空格替换它们,如何阻止它执行此操作?最小的完整示例:

~ ) set lines (cat .lorem); set start 2; set end 4;
~ ) cat .lorem 
once upon a midnight dreary while i pondered weak and weary
over many a quaint and curious volume of forgotten lore
while i nodded nearly napping suddenly there came a tapping
as of some one gently rapping rapping at my chamber door
tis some visiter i muttered tapping at my chamber door
~ ) echo $lines | sed -ne $start\,{$end}p\;{$end}q # Should print lines 2..4
~ ) cat .lorem | sed -ne $start\,{$end}p\;{$end}q
over many a quaint and curious volume of forgotten lore
while i nodded nearly napping suddenly there came a tapping
as of some one gently rapping rapping at my chamber door
~ ) echo $lines
once upon a midnight dreary while i pondered weak and weary over many a quaint and curious volume of forgotten lore while i nodded nearly napping     suddenly there came a tapping as of some one gently rapping rapping at my chamber door tis some visiter i muttered tapping at my chamber door
Run Code Online (Sandbox Code Playgroud)

wat*_*ash 7

从fish 3.4开始,我们可以使用"$(innercommand)"语法。

set lines "$(echo -e 'hi\nthere')"
set -S lines
# $lines: set in global scope, unexported, with 1 elements
# $lines[1]: |hi\nthere|
Run Code Online (Sandbox Code Playgroud)


rid*_*ish 5

fish在换行符上拆分命令替换.这意味着这$lines是一个列表.你可以阅读更多关于此列表.

将列表传递给命令时,列表中的每个条目都将成为单独的参数.echo空格分隔其论点.这解释了你所看到的行为.

请注意,其他shell在这里做同样的事情.例如,在bash中:

lines=$(cat .lorem)
echo $lines
Run Code Online (Sandbox Code Playgroud)

如果要阻止拆分,可以暂时将IFS设置为空:

begin
   set -l IFS
   set lines (cat .lorem)
end
echo $lines
Run Code Online (Sandbox Code Playgroud)

现在$lines将包含换行符.

正如faho所说,read也可以使用并且更短一些:

read -z lines < ~/.lorem
echo $lines
Run Code Online (Sandbox Code Playgroud)

但请考虑是否可能实际上是您想要的换行.正如faho暗示的那样,您的sed脚本可以替换为数组切片:

set lines (cat .lorem)
echo $lines[2..4] # prints lines 2 through 4
Run Code Online (Sandbox Code Playgroud)

  • 这是旧方法……请参阅下面的 @wataash 答案,了解新方法和新方法 (2认同)