When I set any multiline text as a variable in fish, it removes the new line characters and replaces them with space, how can I stop it from doing that? Minimal complete example:
~ ) 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
~ ) cat .lorem | sed -ne $start\,{$end}p\;{$end}q # Should print lines 2..4
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
fish splits command substitutions on newlines. This means that $lines
is a list. You can read more about lists here.
When you pass a list to a command, each entry in the list becomes a separate argument. echo
space-separates its arguments. That explains the behavior you're seeing.
Note that other shells do the same thing here. For example, in bash:
lines=$(cat .lorem)
echo $lines
If you want to prevent the splitting, you can temporarily set IFS to empty:
begin
set -l IFS
set lines (cat .lorem)
end
echo $lines
now $lines
will contain newlines.
As faho says, read
can also be used and is a little shorter:
read -z lines < ~/.lorem
echo $lines
but consider whether splitting on newlines might actually be what you want. As faho hinted, your sed
script can be replaced with array slices:
set lines (cat .lorem)
echo $lines[2..4] # prints lines 2 through 4