【问题标题】:Multi-line variables remove new line character - Fish多行变量删除换行符 - Fish
【发布时间】:2015-12-08 21:11:00
【问题描述】:

当我在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
~ ) 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

【问题讨论】:

标签: shell fish


【解决方案1】:

fish 在换行符上拆分命令替换。这意味着$lines 是一个列表。你可以阅读更多about lists here

当您将列表传递给命令时,列表中的每个条目都会成为单独的参数。 echo 用空格分隔它的参数。这解释了您所看到的行为。

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

lines=$(cat .lorem)
echo $lines

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

begin
   set -l IFS
   set lines (cat .lorem)
end
echo $lines

现在$lines 将包含换行符。

正如 faho 所说,read 也可以使用,而且短一点:

read -z lines < ~/.lorem
echo $lines

但考虑换行符是否真的是你想要的。正如 faho 所暗示的,您的 sed 脚本可以替换为数组切片:

set lines (cat .lorem)
echo $lines[2..4] # prints lines 2 through 4

【讨论】:

    【解决方案2】:

    这不仅仅是删除换行符,而是拆分它们。

    您的变量 $lines 现在是一个列表,每一行都是该列表中的一个元素。

    set lines (cat .lorem)
    for line in $lines
        echo $line
    end
    echo $lines[2]
    printf "%s\n" $lines[2..4]
    

    【讨论】:

    • 谢谢,我知道。我想知道是否有办法阻止这种行为。另一件奇怪的事情是,当您执行set foo bar\nblarch 时,它不会拆分它们,而是将它们设置为一个项目。
    • 目前,如果设置了 IFS,它将在换行符上拆分,如果未设置 IFS,它将不拆分(即它忽略 IFS 的实际值)。你也可以使用read -z
    【解决方案3】:

    将其发送至string split0

    set lines (echo -e 'hi\nthere')
    set -S lines
    # $lines: set in global scope, unexported, with 2 elements
    # $lines[1]: length=2 value=|hi|
    # $lines[2]: length=5 value=|there|
    
    set lines (echo -e 'hi\nthere' | string split0)
    set -S lines
    # $lines: set in global scope, unexported, with 1 elements
    # $lines[1]: length=9 value=|hi\nthere\n|
    

    这在the document中注明:

    如果作为最后一步将输出通过管道传输到 string split 或 string split0,则将使用这些拆分,而不是拆分行。

    【讨论】:

      【解决方案4】:

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

      set lines "$(echo -e 'hi\nthere')"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-09
        • 2018-03-06
        相关资源
        最近更新 更多