如何在源代码中的read -p提示符下将长字符串分成多行?


18

我正在编写将以方式运行的安装脚本/bin/sh

有一行提示输入文件:

read -p "goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n] " REPLY

我想把这条长行分成多行,以使它们都不超过80个字符。我说的是脚本源代码中的几行;与执行脚本时要在屏幕上实际打印的行无关

我尝试过的

  • 第一手方法:

    read -p "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] " REPLY

    这不起作用,因为它无法打印Would you like to add this feature? [Y|n]

  • 第二种方法:

    echo "goat can try change directory if cd fails to do so. " \
        "Would you like to add this feature? [Y|n] "
    read REPLY

    效果不佳。在提示后,它将打印换行符。向中添加-n选项echo无济于事:它只会打印:

    -n goat can try change directory if cd fails to do so. Would you like to add this feature? [Y|n]
    # empty line here
  • 我目前的解决方法是

    printf '%s %s ' \
        "goat can try change directory if cd fails to do so." \
        "Would you like to add this feature? [Y|n] "
    read REPLY

我想知道是否有更好的方法。

请记住,我正在寻找/bin/sh兼容的解决方案。


1
我建议您1.使用更宽的终端和/或编辑器窗口(例如,我在1440p显示器上使用192列乘51行的终端-非常适合拖尾日志文件和在vim中编辑源代码)和2.学会接受有时源代码行会超过80个字符-这是不可避免的。如果我使用较小的字体,则可以拥有更宽的终端,但是当前的设置是宽度和易读性之间的良好折衷。
cas

Answers:


16

首先,让我们通过使用变量将读取结果与文本行解耦:

text="line-1 line-2"             ### Just an example.
read -p "$text" REPLY

这样,问题就变成了:如何为变量分配两行。

当然,首先要做的是:

a="line-1 \
line-2"

这样写,var a实际上就获得了value line-1 line-2

但是您不喜欢这样会导致缺少缩进,那么,我们可能会尝试从here-doc读取行中的行(请注意,here-doc中的缩进行需要制表符,而不是空格,才能正常工作):

    a="$(cat <<-_set_a_variable_
        line-1
        line-2
        _set_a_variable_
    )"
echo "test1 <$a>"

但这将失败,因为实际上写入了两行$a。仅获得一行的解决方法可能是:

    a="$( echo $(cat <<-_set_a_variable_
        line 1
        line 2
        _set_a_variable_
        ) )"
echo "test2 <$a>"

那已经很接近了,但是会带来其他问题。

正确的解决方案。

上面的所有尝试只会使这个问题变得更复杂。

一个非常基本和简单的方法是:

a="line-1"
a="$a line-2"
read -p "$a" REPLY

您的特定示例的代码是(对于任何read支持的shell -p):

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        read -p "$a" REPLY

对于所有其他外壳,请使用:

#!/bin/dash
    a="goat can try change directory if cd fails to do so."
    a="$a Would you like to add this feature? [Y|n] "
# absolute freedom to indent as you see fit.
        printf '%s' "$a"; read REPLY

我知道@BinaryZebra。我只是更正了“ for any shell”,因为不是所有的shell都读过,也不是所有的-p都读过。
terdon

@terdon我们都同意这就是感谢的原因:-)。再次感谢。

1

行尾的反斜杠允许命令在多行中继续执行,而不是输出中的实际换行符。

因此,例如,您的第一个方法就是命令

read -p "goat can try change directory if cd fails to do so. " "Would you like to add this feature? [Y|n] " REPLY

我不确定为什么要阅读以输出多行,但是我只会将其read用于提示行和echo前面的行。

为了使代码在多行中更具可读性,请不要在行之间关闭/打开引号。

尝试这个:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

我不希望它打印两行!我只希望代码在脚本的源代码中每行能容纳80个字符!不过,谢谢您的回答:)
Mateusz Piotrowski

我不喜欢您建议的方法,因为没有缩进。如果我read在函数中缩进,那么您的方法似乎会破坏可读性。
Mateusz Piotrowski

1

我发现@BinaryZebra的方法使用了一个更干净的变量,但是您也可以按照尝试的方式进行操作。您只需要将换行符放在引号内:

read -p "goat can try change directory if cd fails to do so. \
Would you like to add this feature? [Y|n] " REPLY

您认为在每行之后添加换行符会增加可读性吗?因为我不是在寻找插入\n提示的方法。我只是想将代码分成多行,以使每行最多80个字符长。
Mateusz Piotrowski

1
@MateuszPiotrowski哦,这更有意义。那我的回答不是很有用。请编辑您的问题,并澄清您要拆分代码而不是输出。我现在在移动设备上,但是明天看看是否可以提出建议。
terdon

1
@MateuszPiotrowski完成后,我添加了您最初尝试的工作版本。
terdon

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.